From 234922eccee2b0e5d4a4d056ccc666a4df2fbfb7 Mon Sep 17 00:00:00 2001 From: RobertPatzke <robert.patzke@mfp-portal.de> Date: Mon, 7 Nov 2022 13:44:09 +0100 Subject: [PATCH] Update 20221107-2 --- libraries/nRF52840Adc/nRF52840Adc.cpp | 265 ++++++++++++++++++++++++++ libraries/nRF52840Adc/nRF52840Adc.h | 235 +++++++++++++++++++++++ 2 files changed, 500 insertions(+) create mode 100644 libraries/nRF52840Adc/nRF52840Adc.cpp create mode 100644 libraries/nRF52840Adc/nRF52840Adc.h diff --git a/libraries/nRF52840Adc/nRF52840Adc.cpp b/libraries/nRF52840Adc/nRF52840Adc.cpp new file mode 100644 index 0000000..29ca6a9 --- /dev/null +++ b/libraries/nRF52840Adc/nRF52840Adc.cpp @@ -0,0 +1,265 @@ +//----------------------------------------------------------------------------- +// Thema: Social Manufacturing Network / Development Environment +// Datei: nRF52840Gpio.cpp +// Editor: Robert Patzke +// URI/URL: www.mfp-portal.de +//----------------------------------------------------------------------------- +// Lizenz: CC-BY-SA (wikipedia: Creative Commons) +// Datum: 29. Juni 2021 +// + +#include "nRF52840Adc.h" + +// -------------------------------------------------------------------------- +// Konstruktoren +// -------------------------------------------------------------------------- +// + nRF52840Adc::nRF52840Adc() + { +#ifdef nrfClockTASKS_HFCLKSTART + if((*nrfClock_HFCLKSTAT & nrfClock_HFCLKisRunning) == 0) + *nrfClockTASKS_HFCLKSTART = 1; +#endif + + } + +// -------------------------------------------------------------------------- +// Unterklasse Channels +// -------------------------------------------------------------------------- +// +void nRF52840Adc::Channels::clrLists() +{ + for(int i = 0; i < 8; i++) + { + unsList[i] = 0; + srtList[i] = 0; + nrOfChannels = 0; + } +} + +int nRF52840Adc::Channels::add(int chnNr) +{ + for(int i = 0; i < 8; i++) + { + if(unsList[i] == 0) + { + unsList[i] = chnNr; + nrOfChannels++; + return(i); + } + } + return(-1); +} + +void nRF52840Adc::Channels::sort() +{ + int minPos; + int cnt; + int tmp; + + for(cnt = 0; cnt < 8; cnt++) + { + if(unsList[cnt] == 0) break; + srtList[cnt] = unsList[cnt]; + } + + for(int i = 0; i < cnt; i++) + { + minPos = i; // Position des kleinsten Elementes auf Durchgang + + // Position minPos des kleinsten Elementes bestimmen + for(int j = i+1; j < cnt; j++) + if(srtList[j] < srtList[minPos]) + minPos = j; + // minPos zeigt jetzt auf das kleinste Element im unsortierten Bereich + + if(minPos != i) // Wenn ein späteres Element kleiner ist + { // Vertauschen der Felder von i und minPos + tmp = srtList[i]; + srtList[i] = srtList[minPos]; + srtList[minPos] = tmp; + } + } +} + + + +// -------------------------------------------------------------------------- +// Konfigurationen +// -------------------------------------------------------------------------- +// + +// Einstellen der Kanalparameter (CH[].CONFIG) +// +dword nRF52840Adc::cnfChn(int chnIdx, ChnConf conf, AcqTime acqt, PreGain pg) +{ + dword confVal = 0; + + if(conf.inpResistorP) // Beschaltung am Pluseingang + { + if(conf.inpPullUpP) + confVal |= ChnConfPullUpInP; + else + confVal |= ChnConfPullDownInP; + } + else if(conf.inpVoltP) + confVal |= ChnConfV1_2InpP; + + if(conf.inpResistorN) // Beschaltung am Minuseingang + { + if(conf.inpPullUpN) + confVal |= ChnConfPullUpInN; + else + confVal |= ChnConfPullDownInN; + } + else if(conf.inpVoltN) + confVal |= ChnConfV1_2InpN; + + // Einstellen des Vorverstärkers + // + if(pg == pg1_5) + confVal |= ChnConfGain1_5; + else if(pg == pg1_4) + confVal |= ChnConfGain1_4; + else if(pg == pg1_3) + confVal |= ChnConfGain1_3; + else if(pg == pg1_2) + confVal |= ChnConfGain1_2; + else if(pg == pg1) + confVal |= ChnConfGain1; + else if(pg == pg2) + confVal |= ChnConfGain2; + else if(pg == pg4) + confVal |= ChnConfGain4; + + // Auswahl der Referenzspannung + // + if(conf.externRef) + confVal |= ChnConfRefV1_4; + + // Einstellen der Wartezeit vor Wandlung (Ladezeit, Erfassungszeit) + // + if(acqt == acqt5us) + confVal |= ChnConfAcqT5; + else if (acqt == acqt10us) + confVal |= ChnConfAcqT10; + else if (acqt == acqt15us) + confVal |= ChnConfAcqT15; + else if (acqt == acqt20us) + confVal |= ChnConfAcqT20; + else if (acqt == acqt40us) + confVal |= ChnConfAcqT40; + + // Differenzmessung einstellen + // + if(conf.diffMode) + confVal |= ChnConfDiffMode; + + // Burst (Oversampling) aktivieren + // + if(conf.burst) + confVal |= ChnConfBurst; + + return(confVal); +} + +// Zuordnen der Eingänge +// +dword nRF52840Adc::cnfPin(PinNr pinNr) +{ + if(pinNr < aInpSp1) + return((dword) pinNr); + if(pinNr == aInpSp1) + return(9); + if(pinNr == aInpSp2) + return(0x0D); + return(0); +} + + +void nRF52840Adc::config(PinNr pinNrP, PinNr pinNrN, ChnNr chnNr, + ChnConf conf, AcqTime acqt, PreGain pg) +{ + int chnIdx; + volatile ChnConfigs *chnCfgPtr; + + if(chnNr < dc1) // Single-Ended Kanäle + { + // Zeiger auf die Konfigurationsregister festlegen + chnIdx = chnNr; + chnCfgPtr = &(NrfAdcPtr->CH[chnIdx]); + + // Konfigurationsdaten (vom Anwender) eintragen + conf.diffMode = false; // Mögliche Fehler vermeiden + chnCfgPtr->CONFIG = cnfChn(chnIdx,conf,acqt,pg); + + // Eingänge zuordnen + chnCfgPtr->PSELP = cnfPin(pinNrP); + chnCfgPtr->PSELN = 0; // Negativeingang nicht benutzt + + // Vorerst Einzelabtastungen über Task-Anweisung + NrfAdcPtr->RESULT_MAXCNT = 1; + NrfAdcPtr->SAMPLERATE = 0; + + // Speicher zuweisen + NrfAdcPtr->RESULT_PTR = (dword) &channels.seResult; + + // Kanalliste aufbauen + channels.add(chnIdx+1); + } + +} + +// ---------------------------------------------------------------------------- +// Anwendungsfunktionen +// ---------------------------------------------------------------------------- +// +void nRF52840Adc::begin() +{ + // Auflösung vorerst fest eingestellt + NrfAdcPtr->RESOLUTION = 2; // 12 Bit + + // Einschalten des ADC + NrfAdcPtr->ENABLE = 1; + + // Temperatur-Kalibrierung wird später gemacht + // + + // Kanäle sortieren in der Liste + // + channels.sort(); + + // Interrupt-Handling + // ---------------------------------------------------------------------- + // + NrfAdcPtr->INTENCLR = 0xFFFFFFFF; // Vorsichtshalber keine Interrupts + + instPtr0 = this; // Statischen Zeiger auf diese Instanz setzen + + // Interruptvektor setzen + // + __NVIC_SetVector((IRQn_Type) 7, (dword) nRF52840Adc::irqHandler0); + __NVIC_SetPriority((IRQn_Type) 7, 1); + __NVIC_EnableIRQ((IRQn_Type) 7); + +} + + + // ---------------------------------------------------------------------------- + // Ereignisbearbeitung und Interrupts + // ---------------------------------------------------------------------------- + // + +nRF52840Adc *nRF52840Adc::instPtr0 = NULL; + +void nRF52840Adc::irqHandler0() +{ + if(instPtr0 == NULL) return; + instPtr0->irqHandler(); +} + +void nRF52840Adc::irqHandler() +{ + statistic.interrupts++; + +} diff --git a/libraries/nRF52840Adc/nRF52840Adc.h b/libraries/nRF52840Adc/nRF52840Adc.h new file mode 100644 index 0000000..24bb1bf --- /dev/null +++ b/libraries/nRF52840Adc/nRF52840Adc.h @@ -0,0 +1,235 @@ +//----------------------------------------------------------------------------- +// Thema: Social Manufacturing Network / Development Environment +// Datei: nRF52840Adc.h +// Editor: Robert Patzke +// URI/URL: www.mfp-portal.de +//----------------------------------------------------------------------------- +// Lizenz: CC-BY-SA (wikipedia: Creative Commons) +// Datum: 03. Oktober 2022 +// + +#ifndef NRF52840ADC_H +#define NRF52840ADC_H + +#include <stdio.h> +#include "arduinoDefs.h" +#include "IntrfAdc.h" +#include "nrf52840.h" + +#ifndef nrfAdcDef +// ---------------------------------------------------------------------------- +typedef struct _ChnLimits +{ + dword Low; + dword High; +} ChnLimits; + +typedef struct _ChnConfigs +{ + dword PSELP; + dword PSELN; + dword CONFIG; + dword LIMIT; +} ChnConfigs; + +#define ChnConfPullDownInP 0x00000001 +#define ChnConfPullUpInP 0x00000002 +#define ChnConfV1_2InpP 0x00000003 +#define ChnConfPullDownInN 0x00000010 +#define ChnConfPullUpInN 0x00000020 +#define ChnConfV1_2InpN 0x00000030 +#define ChnConfGain1_6 0x00000000 +#define ChnConfGain1_5 0x00000100 +#define ChnConfGain1_4 0x00000200 +#define ChnConfGain1_3 0x00000300 +#define ChnConfGain1_2 0x00000400 +#define ChnConfGain1 0x00000500 +#define ChnConfGain2 0x00000600 +#define ChnConfGain4 0x00000700 +#define ChnConfRefV1_4 0x00001000 +#define ChnConfAcqT3 0x00000000 +#define ChnConfAcqT5 0x00010000 +#define ChnConfAcqT10 0x00020000 +#define ChnConfAcqT15 0x00030000 +#define ChnConfAcqT20 0x00040000 +#define ChnConfAcqT40 0x00050000 +#define ChnConfDiffMode 0x00100000 +#define ChnConfBurst 0x01000000 + + +typedef struct _nrfAdc +{ + volatile dword TASKS_START; // 000 + volatile dword TASKS_SAMPLE; // 004 + volatile dword TASKS_STOP; // 008 + volatile dword TASKS_CALIBRATEOFFSET; // 00C + volatile dword Reserve01[60]; // 010 + volatile dword EVENTS_STARTED; // 100 + volatile dword EVENTS_END; // 104 + volatile dword EVENTS_DONE; // 108 + volatile dword EVENTS_RESULTDONE; // 10C + volatile dword EVENTS_CALIBRATEDONE; // 110 + volatile dword EVENTS_STOPPED; // 114 + volatile ChnLimits EVENTS_CHNLIMIT[8]; // 118 + volatile dword Reserve02[106]; // 158 + volatile dword INTEN; // 300 + volatile dword INTENSET; // 304 + volatile dword INTENCLR; // 308 + volatile dword Reserve03[61]; // 30C + volatile dword STATUS; // 400 + volatile dword Reserve04[63]; // 404 + volatile dword ENABLE; // 500 + volatile dword Reserve05[03]; // 504 + volatile ChnConfigs CH[8]; // 510 + volatile dword Reserve06[24]; // 590 + volatile dword RESOLUTION; // 5F0 + volatile dword OVERSAMPLE; // 5F4 + volatile dword SAMPLERATE; // 5F8 + volatile dword Reserve07[12]; // 5FC + volatile dword RESULT_PTR; // 62C + volatile dword RESULT_MAXCNT; // 630 + volatile dword RESULT_AMOUNT; // 634 +} nrfAdc, *nrfAdcPtr; + +#define NrfAdcBase 0x40007000 +#define NrfAdcPtr ((nrfAdcPtr) NrfAdcBase) + +// Falls noch kein Zugriff auf die Taktfestlegung erfolgte +// +#ifndef NrfClockBase +#define NrfClockBase 0x40000000 +#endif + +#ifndef nrfClockTASKS_HFCLKSTART +#define nrfClockTASKS_HFCLKSTART ((dword *) 0x40000000) +#endif + +#ifndef nrfClock_HFCLKSTAT +#define nrfClock_HFCLKSTAT ((dword *) 0x4000040C) +#endif + +#ifndef nrfClock_HFCLKisRunning +#define nrfClock_HFCLKisRunning 0x00010000 +#endif + +#define nrfAdcDef +// ---------------------------------------------------------------------------- +#endif + +#define P0(x) (x) +#define P1(x) (32+x) + +#ifdef smnNANOBLE33 +// ---------------------------------------------------------------------------- +#define ArdA0Bit 4 +#define ArdA1Bit 5 +#define ArdA2Bit 30 +#define ArdA3Bit 29 +#define ArdA4Bit 31 +#define ArdA5Bit 2 +#define ArdA6Bit 28 +#define ArdA7Bit 3 + +#define ArdA0 P0(4) +#define ArdA1 P0(5) +#define ArdA2 P0(30) +#define ArdA3 P0(29) +#define ArdA4 P0(31) +#define ArdA5 P0(2) +#define ArdA6 P0(28) +#define ArdA7 P0(3) + +#define ArdA0Mask (1 << 4) +#define ArdA1Mask (1 << 5) +#define ArdA2Mask (1 << 30) +#define ArdA3Mask (1 << 29) +#define ArdA4Mask (1 << 31) +#define ArdA5Mask (1 << 2) +#define ArdA6Mask (1 << 28) +#define ArdA7Mask (1 << 3) + +enum AdcChnPin +{ + seC1P = 4, + seC2P = 5, + seC3P = 30, + seC4P = 29, + seC5P = 31, + seC6P = 2, + seC7P = 28, + seC8P = 3 +}; + +// ---------------------------------------------------------------------------- +#endif + +class nRF52840Adc : IntrfAdc +{ + // -------------------------------------------------------------------------- + // Spezifische Datentypen + // -------------------------------------------------------------------------- + // + class Channels + { + public: + int unsList[8]; + int srtList[8]; + int nrOfChannels; + short seResult[8]; + short diResult[4]; + + void clrLists(); + int add(int chnNr); + void sort(); + }; + +private: + // -------------------------------------------------------------------------- + // lokale Variablen + // -------------------------------------------------------------------------- + // + Channels channels; + Statistic statistic; + + // -------------------------------------------------------------------------- + // lokale Funktionen + // -------------------------------------------------------------------------- + // + dword cnfChn(int chnIdx, ChnConf conf, AcqTime acqt, PreGain pg); + dword cnfPin(PinNr pinNr); + +public: + // -------------------------------------------------------------------------- + // Konstruktoren + // -------------------------------------------------------------------------- + // + nRF52840Adc(); + + // -------------------------------------------------------------------------- + // Konfigurationen + // -------------------------------------------------------------------------- + // + void config(PinNr pinNrP, PinNr pinNrN, ChnNr chnNr, ChnConf conf, AcqTime acqt, PreGain pg); + void begin(); + + // -------------------------------------------------------------------------- + // Anwendungsfunktionen + // -------------------------------------------------------------------------- + // + + // ---------------------------------------------------------------------------- + // Ereignisbearbeitung und Interrupts + // ---------------------------------------------------------------------------- + // + static nRF52840Adc *instPtr0; + static void irqHandler0(); + void irqHandler(); + + // -------------------------------------------------------------------------- + // Debugging und globale Variablen + // -------------------------------------------------------------------------- + // + +}; + +#endif //NRF52840ADC_H -- GitLab