diff --git a/Globals.h b/Globals.h index 807417e..9e18082 100644 --- a/Globals.h +++ b/Globals.h @@ -36,7 +36,7 @@ #if defined(__SAM3X8E__) #define ARM_MATH_CM3 -#elif defined(STM32F4XX) || defined(STM32F4) || defined(__MK20DX256__) || defined(__MK66FX1M0__) +#elif defined(STM32F4XX) || defined(STM32F4) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) #define ARM_MATH_CM4 #else #error "Unknown processor type" diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 1cd90f9..a7d1806 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -20,10 +20,8 @@ #include "Globals.h" #include "IO.h" -#if defined(__MK20DX256__) || defined(__MK66FX1M0__) +#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) -// A Teensy 3.1/3.2 -#if defined(__MK20DX256__) #define PIN_LED 13 #define PIN_COS 52 #define PIN_PTT 23 @@ -35,22 +33,8 @@ #define PIN_ADC 5 // A0 #define PIN_RSSI 8 // A2 -// A Teensy 3.6 -#elif defined(__MK66FX1M0__) -#define PIN_LED 13 -#define PIN_COS 52 -#define PIN_PTT 23 -#define PIN_COSLED 22 -#define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 -#define PIN_P25 6 -#define PIN_ADC 5 // A0 -#define PIN_RSSI 8 // A2 -#endif - -#define PDB_CH0C1_TOS 0x0100 -#define PDB_CH0C1_EN 0x01 +#define PDB_CHnC1_TOS 0x0100 +#define PDB_CHnC1_EN 0x0001 const uint16_t DC_OFFSET = 2048U; @@ -66,6 +50,21 @@ extern "C" { io.interrupt(1U); } #endif + +#if defined(EXTERNAL_OSC) + void ftm0_isr() + { + FTM0_CNT = 0; // Reset count value + if ((FTM0_SC & FTM_SC_TOF) == FTM_SC_TOF) // Read the timer overflow flag (TOF in FTM0_SC) + FTM0_SC &= ~FTM_SC_TOF; // If set, clear overflow flag + + // Kick off the ADCs with interrupt at the end of conversion + ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; +#if defined(SEND_RSSI_DATA) + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; +#endif + } +#endif } void CIO::initInt() @@ -96,59 +95,78 @@ void CIO::startInt() #endif // 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 - 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 + SIM_SCGC6 |= SIM_SCGC6_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 +#if defined(EXTERNAL_OSC) + ADC0_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger +#else + ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger +#endif + ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - 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_PG = sum0; + +#if !defined(EXTERNAL_OSC) + ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 +#endif - ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 NVIC_ENABLE_IRQ(IRQ_ADC0); #if defined(SEND_RSSI_DATA) // 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 - 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 + SIM_SCGC3 |= SIM_SCGC3_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 +#if defined(EXTERNAL_OSC) + ADC1_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger +#else + ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger +#endif + ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - ADC1_SC3 = ADC_SC3_CAL; // Begin calibration while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration ; 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_PG = sum1; + +#if !defined(EXTERNAL_OSC) + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 +#endif - ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 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 +#if defined(EXTERNAL_OSC) + // Set up for an external oscillator input + SIM_SCGC6 |= SIM_SCGC6_FTM0; + FTM0_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN; + FTM0_MOD = EXTERNAL_OSC / 24000; + FTM0_CNTIN = 0; + FTM0_SC = FTM_SC_TOIE | FTM_SC_CLKS(3); // External clock, overflow interrupts, no prescaling + NVIC_ENABLE_IRQ(IRQ_FTM0); #else - // 48 MHz for the Teensy 3.1/3.2 - PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus + // Setup PDB for ADC0 (and ADC1) at 24 kHz + SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock + PDB0_MOD = F_BUS / 24000; // Timer period + PDB0_IDLY = 0; // Interrupt delay + PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0 +#if defined(SEND_RSSI_DATA) + PDB0_CH1C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-t9rigger for ADC1 +#endif + PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode + PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling + PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) #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; @@ -231,4 +249,3 @@ void CIO::setP25Int(bool on) } #endif - diff --git a/README.md b/README.md index 3bfea68..030f94c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25. -It runs on the Arduino Due, and the STM32F4xx platforms. Support for the Teensy (3.1/3.2 and 3.6) is being added. +It runs on the Arduino Due and the ST-Micro STM32F4xx platforms. Support for the Teensy (3.1/3.2 and 3.5/3.6) is being added. -In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. +In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is being supplied via the Coocox IDE with ARM GCC. The Teensy support is via the latest beta of Teensyduino. This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.