Advertisement
Guest User

Untitled

a guest
Mar 25th, 2012
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.00 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////////////
  2. // RGB_ADC main.c
  3. //////////////////////////////////////////////////////////////////////////////
  4.  
  5. #include <stdint.h>
  6. #include "compiler.h"
  7. #include "preprocessor.h"
  8. #include "pm.h"
  9. #include "gpio.h"
  10. #include "pwm.h"
  11. #include "adc.h"
  12. #include "tc.h"
  13. #include "intc.h"
  14.  
  15. //////////////////////////////////////////////////////////////////////////////
  16. // clock setup
  17. //////////////////////////////////////////////////////////////////////////////
  18.  
  19. #define FOSC0           12000000                              //!< Osc0 frequency: Hz.
  20. #define OSC0_STARTUP    AVR32_PM_OSCCTRL0_STARTUP_2048_RCOSC  //!< Osc0 startup time: RCOsc periods.
  21.  
  22.  
  23. void init_clock() {
  24.     // source: gpio_local_bus_example.c
  25.  
  26.     // Initialize domain clocks (CPU, HSB, PBA and PBB) to the max frequency available
  27.     // without flash wait states.
  28.     // Some of the registers in the GPIO module are mapped onto the CPU local bus.
  29.     // To ensure maximum transfer speed and cycle determinism, any slaves being
  30.     // addressed by the CPU on the local bus must be able to receive and transmit
  31.     // data on the bus at CPU clock speeds. The consequences of this is that the
  32.     // GPIO module has to run at the CPU clock frequency when local bus transfers
  33.     // are being performed => we want fPBA = fCPU.
  34.  
  35.     // Switch the main clock source to Osc0.
  36.     pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);
  37.  
  38.  
  39.     // Setup PLL0 on Osc0, mul=10 ,no divisor, lockcount=16: 12Mhzx11 = 132MHz output
  40.     pm_pll_setup(&AVR32_PM, 0, // pll.
  41.             10, // mul.
  42.             1, // div.
  43.             0, // osc.
  44.             16); // lockcount.
  45.     // PLL output VCO frequency is 132MHz.
  46.     // We divide it by 2 with the pll_div2=1 to get a main clock at 66MHz.
  47.     pm_pll_set_option(&AVR32_PM, 0, // pll.
  48.             1, // pll_freq.
  49.             1, // pll_div2.
  50.             0); // pll_wbwdisable.
  51.     // Enable the PLL.
  52.     pm_pll_enable(&AVR32_PM, 0);
  53.     // Wait until the PLL output is stable.
  54.     pm_wait_for_pll0_locked(&AVR32_PM);
  55.     // Configure each clock domain to use the main clock divided by 2
  56.     // => fCPU = fPBA = fPBB = 33MHz.
  57.     pm_cksel(&AVR32_PM, 1, // pbadiv.
  58.             0, // pbasel.
  59.             1, // pbbdiv.
  60.             0, // pbbsel.
  61.             1, // hsbdiv=cpudiv
  62.             0); // hsbsel=cpusel
  63.     // Switch the main clock source to PLL0.
  64.     pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0);
  65.  
  66. #define MAIN_CLOCK_FREQ 33000000 // in Hz
  67. }
  68.  
  69. //////////////////////////////////////////////////////////////////////////////
  70. // PWM setup
  71. //////////////////////////////////////////////////////////////////////////////
  72.  
  73. #define S_PWM_PIN           AVR32_PWM_6_0_PIN
  74. #define S_PWM_FUNCTION      AVR32_PWM_6_0_FUNCTION
  75. #define S_PWM_CHANNEL_ID    6
  76.  
  77. #define PWM_CLOCK_DIVIDER AVR32_PWM_CPRE_MCK_DIV_128
  78.  
  79. int get_pwm_cycle_count_from_microseconds(int s) {
  80.     double pwm_clock_freq = (double)MAIN_CLOCK_FREQ / (double)PWM_CLOCK_DIVIDER;
  81.     return pwm_clock_freq * s / 1000000.0;
  82. }
  83.  
  84. static avr32_pwm_channel_t pwm_channel;
  85. void init_pwm() {
  86.     // SET PWM output pins
  87.     gpio_enable_module_pin(S_PWM_PIN, S_PWM_FUNCTION);
  88.  
  89.     // Controller initialization (interrupts disabled)
  90.     static pwm_opt_t pwm_opt;
  91.     pwm_opt.diva = AVR32_PWM_DIVA_CLK_OFF;
  92.     pwm_opt.divb = AVR32_PWM_DIVB_CLK_OFF;
  93.     pwm_opt.prea = AVR32_PWM_PREA_MCK;
  94.     pwm_opt.preb = AVR32_PWM_PREB_MCK;
  95.     pwm_init(&pwm_opt);
  96.  
  97.     // Channel initialization
  98.     pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;
  99.     pwm_channel.CMR.cpol = PWM_POLARITY_HIGH;
  100.     pwm_channel.CMR.cpd = PWM_UPDATE_DUTY; // We want to change the duty cycle, not the period when updating.
  101.     pwm_channel.CMR.cpre = PWM_CLOCK_DIVIDER; // results in 257.8125 kHz
  102.     pwm_channel.cprd = 5156; // 20ms
  103.     pwm_channel.cdty = 5000;
  104. //  pwm_channel.cdty = 232; // 0.9ms
  105.     //pwm_channel.cdty = 541; // 2.1ms
  106.     pwm_channel.cupd = 0;
  107.  
  108.     pwm_channel_init(S_PWM_CHANNEL_ID, &pwm_channel);
  109.     pwm_start_channels(1 << 6);
  110. }
  111.  
  112. // Set new values into pwm channels
  113. void update_pwm(unsigned int val) {
  114. //  pwm_channel.cdty = 232+3.09*val;
  115.     pwm_channel.cdty = val+1;
  116.     pwm_channel_init(S_PWM_CHANNEL_ID, &pwm_channel);
  117. }
  118.  
  119. //////////////////////////////////////////////////////////////////////////////
  120. // TimerCounter setup
  121. // acts as a trigger for ADC
  122. //////////////////////////////////////////////////////////////////////////////
  123. void init_tc() {
  124.     /*
  125.      * We want a TC generating triggers for our ADC converter.
  126.      * Since we'd like to sample audio data, we'd like to get up to 20kHz sample rate.
  127.      * So therefore a 40kHz sampling rate is our goal.
  128.      *
  129.      * The triggers should come out at TIOA0.
  130.      */
  131.  
  132.     gpio_enable_module_pin(AVR32_TC_A0_0_1_PIN, AVR32_TC_A0_0_1_FUNCTION);
  133.  
  134.     volatile avr32_tc_t *tc = &AVR32_TC;
  135.  
  136.     tc_waveform_opt_t waveform_opt =
  137.       {
  138.         .channel  = 0,
  139.  
  140.         // No software or external triggers
  141.         .bswtrg   = TC_EVT_EFFECT_NOOP,
  142.         .beevt    = TC_EVT_EFFECT_NOOP,
  143.         .bcpc     = TC_EVT_EFFECT_NOOP,
  144.         .bcpb     = TC_EVT_EFFECT_NOOP,
  145.  
  146.         .aswtrg   = TC_EVT_EFFECT_NOOP,
  147.         .aeevt    = TC_EVT_EFFECT_NOOP,
  148.         .enetrg   = FALSE,                        // External event trigger enable.
  149.         .eevt     = TC_EXT_EVENT_SEL_TIOB_INPUT,  // External event selection.
  150.         .eevtedg  = TC_SEL_NO_EDGE,               // External event edge selection.
  151.         .cpcdis   = FALSE,                        // Counter disable when RC compare.
  152.         .cpcstop  = FALSE,                        // Counter clock stopped with RC compare.
  153.  
  154.         // Set waveform parameters
  155.         .acpc     = 2,                                    // RC compare effect on TIOA: clear
  156.         .acpa     = 1,                                    // RA compare effect on TIOA: set
  157.  
  158.         .wavsel   = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,   // Waveform selection: Up mode without automatic trigger on RC compare.
  159.  
  160.         .burst    = 0,           // No Burst
  161.         .clki     = 0,           // No Clock inversion.
  162.         .tcclks   = 3            // Internal source clock 4, connected to fPBA / 32. -> 1.031250 MHz
  163.       };
  164.  
  165.     // Our PWM now starts on Reaching RA and lasts till RC, where the counter
  166.     // resets to 0
  167.     tc_init_waveform(tc, &waveform_opt);
  168.  
  169.     // We want 40kHz ticks
  170.     tc_write_rc(tc, 0, 25);
  171.     // and the duty cycle is just half of the period.
  172.     // it really doesn't matter since we are just looking for rising edges.
  173.     tc_write_ra(tc, 0, 10);
  174.  
  175.     //start the channel
  176.     tc_start(tc, 0);
  177. }
  178.  
  179. //////////////////////////////////////////////////////////////////////////////
  180. // ADC setup
  181. //////////////////////////////////////////////////////////////////////////////
  182. #  define ADC_CHANNEL     1
  183. #  define ADC_PIN         AVR32_ADC_AD_1_PIN
  184. #  define ADC_FUNCTION    AVR32_ADC_AD_1_FUNCTION
  185.  
  186. void init_adc () {
  187.       // GPIO pin/adc-function map.
  188.       static const gpio_map_t ADC_GPIO_MAP =
  189.       {
  190.         {ADC_PIN, ADC_FUNCTION}
  191.       };
  192.  
  193.       volatile avr32_adc_t *adc = &AVR32_ADC; // ADC IP registers address
  194.  
  195.  
  196.       // Assign the on-board sensors to their ADC channel.
  197.       unsigned short adc_channel = ADC_CHANNEL;
  198.       // Assign and enable GPIO pins to the ADC function.
  199.       gpio_enable_module(ADC_GPIO_MAP, sizeof(ADC_GPIO_MAP) / sizeof(ADC_GPIO_MAP[0]));
  200.  
  201.       // configure ADC
  202.       // Lower the ADC clock to match the ADC characteristics (because we configured
  203.       // the CPU clock to 33MHz, and the ADC clock requires less than 5 MHz for 10 bit ADC,
  204.       // therefore prescale by ;
  205.       // cf. the ADC Characteristic section in the datasheet).
  206.       // These numbers are wrong currently!
  207.       AVR32_ADC.mr |= 0x3 << AVR32_ADC_MR_PRESCAL_OFFSET;
  208.  
  209.       // We want to enable the hardware trigger mode on TIOA0 / Internal Trigger 0
  210.       AVR32_ADC.mr |= 1;
  211.  
  212.       // Enable EOC interrupt
  213.       AVR32_ADC.ier = 1 << ADC_CHANNEL;
  214.  
  215.       /*
  216.        * This function sets startup- and "sample and hold"-time to a good and high value
  217.        * so that the capacitors have time to load. Moreover it sets the 8-bit (instead of 10bit)
  218.        * low-resolution mode if USE_ADC_8_BITS is defined.
  219.        */
  220.       adc_configure(adc);
  221.  
  222.       // Enable the ADC channels.
  223.       adc_enable(adc,adc_channel);
  224. }
  225.  
  226. // ADC value converted
  227. volatile uint8_t adc_ready = 0;
  228.  
  229. __attribute__((__interrupt__))
  230. static void adc_int_handler(void) {
  231.     adc_ready = 1;
  232. //  volatile avr32_adc_t *adc = &AVR32_ADC;
  233. //  update_pwm(*((unsigned long * )(&(adc->cdr0))));
  234. }
  235.  
  236. //////////////////////////////////////////////////////////////////////////////
  237. // main
  238. //////////////////////////////////////////////////////////////////////////////
  239.  
  240. void init_intc() {
  241.     Disable_global_interrupt();
  242.  
  243.     INTC_init_interrupts();
  244.     INTC_register_interrupt(&adc_int_handler, AVR32_ADC_IRQ, AVR32_INTC_INT0);
  245.  
  246.     Enable_global_interrupt();
  247. }
  248.  
  249. int main() {
  250.     init_clock();
  251.     init_intc();
  252.     init_pwm();
  253.     init_tc();
  254.     init_adc();
  255.  
  256.     volatile avr32_adc_t *adc = &AVR32_ADC;
  257.  
  258. //  gpio_local_init();
  259. //  gpio_local_enable_pin_output_driver(AVR32_PIN_PA06);
  260. //  gpio_set_gpio_pin(AVR32_PIN_PA06);
  261.  
  262.     while (1) {
  263.         if (adc_ready == 1) {
  264.             adc_ready = 0;
  265.             update_pwm(*((unsigned long * )((&(adc->cdr0)))));
  266.         }
  267.     }
  268.  
  269.     return 0;
  270. }
  271.  
  272. //////////////////////////////////////////////////////////////////////////////
  273. // EOF
  274. //////////////////////////////////////////////////////////////////////////////
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement