/* * TCD0_PLL_fuer_Landolt.cpp * * DDS Code von S.Landolt * * Created: 12.03.2021 * Author : Devil-Elec * Code angepasst für AVR128DB48 mit TCD0 und PLL * Board: AVR128DB48 Curiosity Nano * * Ausgangspin: PA5 */ // #define TIMERTAKT_PLL // für 48MHz PLL Takt "einkommentieren" #include #include void initPins (void); void initTCD0 (void); void initOnboard16MHzOscillator (void); void initInternal16MHzOscillator48MHzPLL (void); const uint16_t RESOLUTION = 256; #if defined (TIMERTAKT_PLL) const uint32_t PWM = 48000000UL/RESOLUTION; // = 187'500 (48MHz Timertakt) #else const uint16_t PWM = F_CPU/RESOLUTION; // = 62'500 (16MHz CPU und Timertakt) #endif const uint16_t TonA4 = 440; const uint16_t A4_Phasendelta = (uint16_t)(65536UL*TonA4/PWM); uint16_t Phase; const uint8_t Sinus[256] PROGMEM = { 127, 130, 133, 136, 139, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 178, 181, 184, 187, 190, 192, 195, 198, 200, 203, 205, 208, 210, 212, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 234, 236, 238, 239, 240, 242, 243, 244, 245, 247, 248, 249, 249, 250, 251, 252, 252, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 252, 252, 251, 250, 249, 249, 248, 247, 245, 244, 243, 242, 240, 239, 238, 236, 234, 233, 231, 229, 227, 225, 223, 221, 219, 217, 215, 212, 210, 208, 205, 203, 200, 198, 195, 192, 190, 187, 184, 181, 178, 176, 173, 170, 167, 164, 161, 158, 155, 152, 149, 146, 143, 139, 136, 133, 130, 127, 124, 121, 118, 115, 111, 108, 105, 102, 99, 96, 93, 90, 87, 84, 81, 78, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 115, 118, 121, 124 }; int main(void) { #if defined (TIMERTAKT_PLL) initInternal16MHzOscillator48MHzPLL(); #else initOnboard16MHzOscillator(); // external 16MHz Oscillator - PLL not working - Errata #endif initPins(); initTCD0(); while (1) { Phase += A4_Phasendelta; TCD0.CMPBSET = pgm_read_byte(&(Sinus[Phase >> 8])); // Pulsweite TCD0.CTRLE = TCD_SYNC_bm; // aktualisiert die double buffered register while (!(TCD0.INTFLAGS & (TCD_OVF_bm))) { ; } // ohne jitter: sleep plus interrupt TCD0.INTFLAGS = TCD_OVF_bm; // delete interrupt flag } } void initPins (void) { VPORTA_DIR = _BV(PIN5_bm); // PA5 Output } void initTCD0(void) // 12 Bit Timer -->> max 4095 { /* Errata: The PLL Will Not Run when Using XOSCHF with an External Crystal. When the PLL is configured to run from an external source (SOURCE in CLKCTRL.PLLCTRLA is ‘1’), the PLL will only run if XOSCHF is configured to use an external clock (SELHF in CLKCTRL.XOSCHFCTRLA is ‘1’). It will not work with an external crystal. */ CPU_CCP = CCP_IOREG_gc; #if defined (TIMERTAKT_PLL) TCD0.CTRLA = TCD_CLKSEL_PLL_gc; // TCD0 wird von PLL getaktet #else TCD0.CTRLA = TCD_CLKSEL_EXTCLK_gc; // TCD0 wird von externen Takt oder crystal oscillator getaktet #endif TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc; TCD0.CMPBCLR = RESOLUTION-1; // Timer TOP Einstellung, Periodendauer /* Enable the PWM channels */ CPU_CCP = CCP_IOREG_gc; TCD0.FAULTCTRL = (TCD_CMPBEN_bm | TCD_CMPB_bm); // only WOB while (!(TCD0.STATUS & TCD_ENRDY_bm)) { ; } // Wait for TCD to be ready for enabling TCD0.CTRLA |= TCD_ENABLE_bm; // enable TCD0 } void initOnboard16MHzOscillator (void) { CPU_CCP = CCP_IOREG_gc; CLKCTRL.XOSCHFCTRLA = ( CLKCTRL_RUNSTDBY_bm // Run standby enabled | CLKCTRL_CSUTHF_4K_gc // 4k XOSCHF cycles | CLKCTRL_FRQRANGE_16M_gc // Max 16 MHz XTAL Frequency | CLKCTRL_SELHF_CRYSTAL_gc // Typ: External Crystal | CLKCTRL_ENABLE_bm // External high-frequency Oscillator enabled ); // Confirm crystal oscillator start-up while(!(CLKCTRL.MCLKSTATUS & CLKCTRL_EXTS_bm)) { ; } // Select External Clock Source and enable Pin Clock Out CPU_CCP = CCP_IOREG_gc; CLKCTRL.MCLKCTRLA = (CLKCTRL_CLKSEL_EXTCLK_gc | CLKCTRL_CLKOUT_bm); // wait for system oscillator changing to finish while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) { ; } } void initInternal16MHzOscillator48MHzPLL (void) { CPU_CCP = CCP_IOREG_gc; CLKCTRL.OSCHFCTRLA = ( CLKCTRL_FREQSEL_16M_gc ); // Internal OSCHF 16MHz // wait internal oscillator is stable while(!(CLKCTRL.MCLKSTATUS & CLKCTRL_OSCHFS_bm)) { ; } // Set the PLL to use OSCHF as source, and select 3x multiplication factor CPU_CCP = CCP_IOREG_gc; CLKCTRL.PLLCTRLA = CLKCTRL_MULFAC_3x_gc; // 48MHz PLL // wait for system oscillator changing to finish while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) { ; } }