Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //////////////////////////////////////////////////////////////////////////////
- // RGB_ADC main.c
- //////////////////////////////////////////////////////////////////////////////
- #include <stdint.h>
- #include "compiler.h"
- #include "preprocessor.h"
- #include "pm.h"
- #include "gpio.h"
- #include "pwm.h"
- #include "adc.h"
- #include "tc.h"
- #include "intc.h"
- //////////////////////////////////////////////////////////////////////////////
- // clock setup
- //////////////////////////////////////////////////////////////////////////////
- #define FOSC0 12000000 //!< Osc0 frequency: Hz.
- #define OSC0_STARTUP AVR32_PM_OSCCTRL0_STARTUP_2048_RCOSC //!< Osc0 startup time: RCOsc periods.
- void init_clock() {
- // source: gpio_local_bus_example.c
- // Initialize domain clocks (CPU, HSB, PBA and PBB) to the max frequency available
- // without flash wait states.
- // Some of the registers in the GPIO module are mapped onto the CPU local bus.
- // To ensure maximum transfer speed and cycle determinism, any slaves being
- // addressed by the CPU on the local bus must be able to receive and transmit
- // data on the bus at CPU clock speeds. The consequences of this is that the
- // GPIO module has to run at the CPU clock frequency when local bus transfers
- // are being performed => we want fPBA = fCPU.
- // Switch the main clock source to Osc0.
- pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);
- // Setup PLL0 on Osc0, mul=10 ,no divisor, lockcount=16: 12Mhzx11 = 132MHz output
- pm_pll_setup(&AVR32_PM, 0, // pll.
- 10, // mul.
- 1, // div.
- 0, // osc.
- 16); // lockcount.
- // PLL output VCO frequency is 132MHz.
- // We divide it by 2 with the pll_div2=1 to get a main clock at 66MHz.
- pm_pll_set_option(&AVR32_PM, 0, // pll.
- 1, // pll_freq.
- 1, // pll_div2.
- 0); // pll_wbwdisable.
- // Enable the PLL.
- pm_pll_enable(&AVR32_PM, 0);
- // Wait until the PLL output is stable.
- pm_wait_for_pll0_locked(&AVR32_PM);
- // Configure each clock domain to use the main clock divided by 2
- // => fCPU = fPBA = fPBB = 33MHz.
- pm_cksel(&AVR32_PM, 1, // pbadiv.
- 0, // pbasel.
- 1, // pbbdiv.
- 0, // pbbsel.
- 1, // hsbdiv=cpudiv
- 0); // hsbsel=cpusel
- // Switch the main clock source to PLL0.
- pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0);
- #define MAIN_CLOCK_FREQ 33000000 // in Hz
- }
- //////////////////////////////////////////////////////////////////////////////
- // PWM setup
- //////////////////////////////////////////////////////////////////////////////
- #define S_PWM_PIN AVR32_PWM_6_0_PIN
- #define S_PWM_FUNCTION AVR32_PWM_6_0_FUNCTION
- #define S_PWM_CHANNEL_ID 6
- #define PWM_CLOCK_DIVIDER AVR32_PWM_CPRE_MCK_DIV_128
- int get_pwm_cycle_count_from_microseconds(int s) {
- double pwm_clock_freq = (double)MAIN_CLOCK_FREQ / (double)PWM_CLOCK_DIVIDER;
- return pwm_clock_freq * s / 1000000.0;
- }
- static avr32_pwm_channel_t pwm_channel;
- void init_pwm() {
- // SET PWM output pins
- gpio_enable_module_pin(S_PWM_PIN, S_PWM_FUNCTION);
- // Controller initialization (interrupts disabled)
- static pwm_opt_t pwm_opt;
- pwm_opt.diva = AVR32_PWM_DIVA_CLK_OFF;
- pwm_opt.divb = AVR32_PWM_DIVB_CLK_OFF;
- pwm_opt.prea = AVR32_PWM_PREA_MCK;
- pwm_opt.preb = AVR32_PWM_PREB_MCK;
- pwm_init(&pwm_opt);
- // Channel initialization
- pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;
- pwm_channel.CMR.cpol = PWM_POLARITY_HIGH;
- pwm_channel.CMR.cpd = PWM_UPDATE_DUTY; // We want to change the duty cycle, not the period when updating.
- pwm_channel.CMR.cpre = PWM_CLOCK_DIVIDER; // results in 257.8125 kHz
- pwm_channel.cprd = 5156; // 20ms
- pwm_channel.cdty = 5000;
- // pwm_channel.cdty = 232; // 0.9ms
- //pwm_channel.cdty = 541; // 2.1ms
- pwm_channel.cupd = 0;
- pwm_channel_init(S_PWM_CHANNEL_ID, &pwm_channel);
- pwm_start_channels(1 << 6);
- }
- // Set new values into pwm channels
- void update_pwm(unsigned int val) {
- // pwm_channel.cdty = 232+3.09*val;
- pwm_channel.cdty = val+1;
- pwm_channel_init(S_PWM_CHANNEL_ID, &pwm_channel);
- }
- //////////////////////////////////////////////////////////////////////////////
- // TimerCounter setup
- // acts as a trigger for ADC
- //////////////////////////////////////////////////////////////////////////////
- void init_tc() {
- /*
- * We want a TC generating triggers for our ADC converter.
- * Since we'd like to sample audio data, we'd like to get up to 20kHz sample rate.
- * So therefore a 40kHz sampling rate is our goal.
- *
- * The triggers should come out at TIOA0.
- */
- gpio_enable_module_pin(AVR32_TC_A0_0_1_PIN, AVR32_TC_A0_0_1_FUNCTION);
- volatile avr32_tc_t *tc = &AVR32_TC;
- tc_waveform_opt_t waveform_opt =
- {
- .channel = 0,
- // No software or external triggers
- .bswtrg = TC_EVT_EFFECT_NOOP,
- .beevt = TC_EVT_EFFECT_NOOP,
- .bcpc = TC_EVT_EFFECT_NOOP,
- .bcpb = TC_EVT_EFFECT_NOOP,
- .aswtrg = TC_EVT_EFFECT_NOOP,
- .aeevt = TC_EVT_EFFECT_NOOP,
- .enetrg = FALSE, // External event trigger enable.
- .eevt = TC_EXT_EVENT_SEL_TIOB_INPUT, // External event selection.
- .eevtedg = TC_SEL_NO_EDGE, // External event edge selection.
- .cpcdis = FALSE, // Counter disable when RC compare.
- .cpcstop = FALSE, // Counter clock stopped with RC compare.
- // Set waveform parameters
- .acpc = 2, // RC compare effect on TIOA: clear
- .acpa = 1, // RA compare effect on TIOA: set
- .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, // Waveform selection: Up mode without automatic trigger on RC compare.
- .burst = 0, // No Burst
- .clki = 0, // No Clock inversion.
- .tcclks = 3 // Internal source clock 4, connected to fPBA / 32. -> 1.031250 MHz
- };
- // Our PWM now starts on Reaching RA and lasts till RC, where the counter
- // resets to 0
- tc_init_waveform(tc, &waveform_opt);
- // We want 40kHz ticks
- tc_write_rc(tc, 0, 25);
- // and the duty cycle is just half of the period.
- // it really doesn't matter since we are just looking for rising edges.
- tc_write_ra(tc, 0, 10);
- //start the channel
- tc_start(tc, 0);
- }
- //////////////////////////////////////////////////////////////////////////////
- // ADC setup
- //////////////////////////////////////////////////////////////////////////////
- # define ADC_CHANNEL 1
- # define ADC_PIN AVR32_ADC_AD_1_PIN
- # define ADC_FUNCTION AVR32_ADC_AD_1_FUNCTION
- void init_adc () {
- // GPIO pin/adc-function map.
- static const gpio_map_t ADC_GPIO_MAP =
- {
- {ADC_PIN, ADC_FUNCTION}
- };
- volatile avr32_adc_t *adc = &AVR32_ADC; // ADC IP registers address
- // Assign the on-board sensors to their ADC channel.
- unsigned short adc_channel = ADC_CHANNEL;
- // Assign and enable GPIO pins to the ADC function.
- gpio_enable_module(ADC_GPIO_MAP, sizeof(ADC_GPIO_MAP) / sizeof(ADC_GPIO_MAP[0]));
- // configure ADC
- // Lower the ADC clock to match the ADC characteristics (because we configured
- // the CPU clock to 33MHz, and the ADC clock requires less than 5 MHz for 10 bit ADC,
- // therefore prescale by ;
- // cf. the ADC Characteristic section in the datasheet).
- // These numbers are wrong currently!
- AVR32_ADC.mr |= 0x3 << AVR32_ADC_MR_PRESCAL_OFFSET;
- // We want to enable the hardware trigger mode on TIOA0 / Internal Trigger 0
- AVR32_ADC.mr |= 1;
- // Enable EOC interrupt
- AVR32_ADC.ier = 1 << ADC_CHANNEL;
- /*
- * This function sets startup- and "sample and hold"-time to a good and high value
- * so that the capacitors have time to load. Moreover it sets the 8-bit (instead of 10bit)
- * low-resolution mode if USE_ADC_8_BITS is defined.
- */
- adc_configure(adc);
- // Enable the ADC channels.
- adc_enable(adc,adc_channel);
- }
- // ADC value converted
- volatile uint8_t adc_ready = 0;
- __attribute__((__interrupt__))
- static void adc_int_handler(void) {
- adc_ready = 1;
- // volatile avr32_adc_t *adc = &AVR32_ADC;
- // update_pwm(*((unsigned long * )(&(adc->cdr0))));
- }
- //////////////////////////////////////////////////////////////////////////////
- // main
- //////////////////////////////////////////////////////////////////////////////
- void init_intc() {
- Disable_global_interrupt();
- INTC_init_interrupts();
- INTC_register_interrupt(&adc_int_handler, AVR32_ADC_IRQ, AVR32_INTC_INT0);
- Enable_global_interrupt();
- }
- int main() {
- init_clock();
- init_intc();
- init_pwm();
- init_tc();
- init_adc();
- volatile avr32_adc_t *adc = &AVR32_ADC;
- // gpio_local_init();
- // gpio_local_enable_pin_output_driver(AVR32_PIN_PA06);
- // gpio_set_gpio_pin(AVR32_PIN_PA06);
- while (1) {
- if (adc_ready == 1) {
- adc_ready = 0;
- update_pwm(*((unsigned long * )((&(adc->cdr0)))));
- }
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////////
- // EOF
- //////////////////////////////////////////////////////////////////////////////
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement