From 584134d1d1653412baa52cecc90501588a9bf520 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 10 Nov 2016 19:45:35 +0000 Subject: [PATCH 1/2] Add more Teensy IO code. --- IOTeensy.cpp | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index bb58f20..78a058a 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -32,6 +32,8 @@ #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 +#define PIN_ADC 5 // A0 +#define PIN_RSSI 8 // A2 // A Teensy 3.6 #elif defined(__MK66FX1M0__) @@ -43,6 +45,8 @@ #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 +#define PIN_ADC 5 // A0 +#define PIN_RSSI 8 // A2 #endif const uint16_t DC_OFFSET = 2048U; @@ -52,6 +56,11 @@ extern "C" { { io.interrupt(); } + + void adc1_isr() + { + io.interrupt(); + } } void CIO::initInt() @@ -82,17 +91,26 @@ void CIO::startInt() ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - ADC0_SC1A = ADC_SC1_AIEN | 5; // Enable ADC interrupt, use A0 + + ADC0_SC3 = ADC_SC3_CAL; // Begin calibration + while ((ADC0_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration + ; + + uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; // Plus side gain + sum0 = (sum0 / 2U) | 0x8000U; + ADC0_PG = sum0; + + ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 NVIC_ENABLE_IRQ(IRQ_ADC0); // Setup PDB for ADC0 at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock #if F_BUS == 60000000 // 60 MHz for the Teensy 3.5/3.6 - PDB0_MOD = 2500; // Timer period for 60 MHz bus + PDB0_MOD = 2500 - 1; // Timer period for 60 MHz bus #else // 48 MHz for the Teensy 3.1/3.2 - PDB0_MOD = 2000; // Timer period for 48 MHz bus + PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus #endif PDB0_IDLY = 0; // Interrupt delay PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger @@ -103,10 +121,22 @@ void CIO::startInt() #if defined(SEND_RSSI_DATA) // Initialise ADC1 conversion to be triggered by the PDB + ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | + ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time + ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb + ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger + ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - // Setup interrupt on ADC1 conversion finished + ADC1_SC3 = ADC_SC3_CAL; // Begin calibration + while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration + ; - // Setup PDB for ADC1 at 24 kHz + uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; // Plus side gain + sum1 = (sum1 / 2U) | 0x8000U; + ADC1_PG = sum1; + + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A0 + NVIC_ENABLE_IRQ(IRQ_ADC1); #endif // Initialise the DAC From 823b68d5ed2ad41e93f6fec6b9b6256f17841239 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 10 Nov 2016 20:15:06 +0000 Subject: [PATCH 2/2] More ADC IRQ work for the Teensy. --- IOTeensy.cpp | 96 ++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 78a058a..c555f7d 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -49,15 +49,13 @@ #define PIN_RSSI 8 // A2 #endif +#define PDB_CH0C1_TOS 0x0100 +#define PDB_CH0C1_EN 0x01 + const uint16_t DC_OFFSET = 2048U; extern "C" { - void adc0_isr() - { - io.interrupt(); - } - - void adc1_isr() + void pdb_isr() { io.interrupt(); } @@ -80,12 +78,9 @@ void CIO::initInt() #endif } -#define PDB_CH0C1_TOS 0x0100 -#define PDB_CH0C1_EN 0x01 - void CIO::startInt() { - // Initialise ADC0 conversion to be triggered by the PDB + // Initialise ADC0 ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb @@ -100,27 +95,8 @@ void CIO::startInt() sum0 = (sum0 / 2U) | 0x8000U; ADC0_PG = sum0; - ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 - NVIC_ENABLE_IRQ(IRQ_ADC0); - - // Setup PDB for ADC0 at 24 kHz - SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock -#if F_BUS == 60000000 - // 60 MHz for the Teensy 3.5/3.6 - PDB0_MOD = 2500 - 1; // Timer period for 60 MHz bus -#else - // 48 MHz for the Teensy 3.1/3.2 - PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus -#endif - PDB0_IDLY = 0; // Interrupt delay - PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger - PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | - PDB_SC_CONT | PDB_SC_PRESCALER(7) | PDB_SC_MULT(1) | - PDB_SC_LDOK; - PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) - #if defined(SEND_RSSI_DATA) - // Initialise ADC1 conversion to be triggered by the PDB + // Initialise ADC1 ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb @@ -134,11 +110,25 @@ void CIO::startInt() uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; // Plus side gain sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; - - ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A0 - NVIC_ENABLE_IRQ(IRQ_ADC1); #endif + // Setup PDB for ADC0 at 24 kHz + SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock +#if F_BUS == 60000000 + // 60 MHz for the Teensy 3.5/3.6 + PDB0_MOD = 2500 - 1; // Timer period for 60 MHz bus +#else + // 48 MHz for the Teensy 3.1/3.2 + PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus +#endif + PDB0_IDLY = 0; // Interrupt delay + PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger + PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | + PDB_SC_CONT | PDB_SC_PRESCALER(7) | PDB_SC_MULT(1) | + PDB_SC_LDOK; + PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) + NVIC_ENABLE_IRQ(IRQ_PDB); + // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 @@ -150,29 +140,39 @@ void CIO::startInt() void CIO::interrupt() { - if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { - uint8_t control = MARK_NONE; - uint16_t sample = DC_OFFSET; + uint8_t control = MARK_NONE; + uint16_t sample = DC_OFFSET; - m_txBuffer.get(sample, control); - *(int16_t *)&(DAC0_DAT0L) = sample; + m_txBuffer.get(sample, control); + *(int16_t *)&(DAC0_DAT0L) = sample; - sample = ADC0_RA; - m_rxBuffer.put(sample, control); + ADC0_SC1A = PIN_ADC; // Start read on A0 + + // Wait for the read to complete + while ((ADC0_SC1A & ADC_SC1_COCO) != ADC_SC1_COCO) + ; + + sample = ADC0_RA; + m_rxBuffer.put(sample, control); #if !defined(SEND_RSSI_DATA) - m_rssiBuffer.put(0U); + m_rssiBuffer.put(0U); #endif - m_watchdog++; - } - #if defined(SEND_RSSI_DATA) - if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { - uint16_t rssi = ADC1_RA; - m_rssiBuffer.put(rssi); - } + ADC1_SC1A = PIN_RSSI; // Start read on A2 + + // Wait for the read to complete + while ((ADC1_SC1A & ADC_SC1_COCO) != ADC_SC1_COCO) + ; + + uint16_t rssi = ADC1_RA; + m_rssiBuffer.put(rssi); #endif + + PDB0_SC &= ~PDB_SC_PDBIF; // Clear interrupt flag + + m_watchdog++; } bool CIO::getCOSInt()