static void enable_output(const channel_def_t* channel, int freq) { if (channel->externally_driven) { uint32_t clock = sysclk_get_peripheral_bus_hz(channel->ex.timer) / 32; // clock source is PB / 32 uint32_t rc = clock / freq; // check for over/underflow if (rc > 0xffff) rc = 0xffff; else if (rc < 8) rc = 8; // set up RA, RB, and RC. always use 50% duty cycle (RA = RB = RC/2) tc_write_ra(channel->ex.timer, channel->ex.channel, (uint16_t)rc / 2); tc_write_rb(channel->ex.timer, channel->ex.channel, (uint16_t)rc / 2); tc_write_rc(channel->ex.timer, channel->ex.channel, (uint16_t)rc); tc_start(channel->ex.timer, channel->ex.channel); } else if (channel->in.active_level) { gpio_set_pin_high(channel->in.pin1); } else { gpio_set_pin_low(channel->in.pin1); } }
/** * \brief Measure touch sensors and do appropriate action */ void touch_handler(void) { uint16_t qt_measurement_status; if (time_to_measure_touch) { time_to_measure_touch = false; do { qt_measurement_status = qt_measure_sensors(current_time_ms); #ifdef _DEBUG_INTERFACE_ QDebug_SendData(qt_measurement_status); #endif } while (qt_measurement_status & QTLIB_BURST_AGAIN); #ifdef _DEBUG_INTERFACE_ QDebug_ProcessCommands(); #endif if (qt_measure_data.qt_touch_status.sensor_states[0] & 0x01) { LED_On(LED1); } else { LED_Off(LED1); } if (qt_measure_data.qt_touch_status.sensor_states[0] & 0x02) { uint8_t slider_pos = qt_measure_data.qt_touch_status.rotor_slider_values[0]; tc_write_rb(&AVR32_TC0, 0, (slider_pos + 1)); LED_On(LED2); } else { LED_Off(LED2); } } }
/** * \brief Initializes the TC subsystem ready to generate a LED PWM wave. * * Initializes the on-chip TC module in PWM generation mode, and configures the * board LED as an output so that the LED brightness can be adjusted. */ static void pwm_timer_init(void) { // Assign output pin to timer/counter 0 channel B gpio_enable_module_pin(AVR32_TC0_B0_0_0_PIN, AVR32_TC0_B0_0_0_FUNCTION); // Timer waveform options const tc_waveform_opt_t waveform_options = { //! Channel selection. .channel = 0, //! Software trigger effect on TIOB. .bswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOB. .beevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOB. .bcpc = TC_EVT_EFFECT_CLEAR, //! RB compare effect on TIOB. .bcpb = TC_EVT_EFFECT_SET, //! Software trigger effect on TIOA. .aswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOA. .aeevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOA. .acpc = TC_EVT_EFFECT_NOOP, //! RA compare effect on TIOA. .acpa = TC_EVT_EFFECT_NOOP, //! Waveform selection .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, //! External event trigger enable. .enetrg = false, //! External event selection (non-zero for Channel B to work) .eevt = !0, //! External event edge selection. .eevtedg = TC_SEL_NO_EDGE, //! Counter disable when RC compare. .cpcdis = false, //! Counter clock stopped with RC compare. .cpcstop = false, //! Burst signal selection. .burst = false, //! Clock inversion selection. .clki = false, //! Internal source clock 5, fPBA/128. .tcclks = TC_CLOCK_SOURCE_TC5, }; // Setup timer/counter waveform mode sysclk_enable_peripheral_clock(&AVR32_TC0); tc_init_waveform(&AVR32_TC0, &waveform_options); // Write the TOP (RC) and COMPARE (RB) values tc_write_rb(&AVR32_TC0, 0, 1); // Set RB value. tc_write_rc(&AVR32_TC0, 0, 255); // Set RC value. // Start the timer PWM channel tc_start(&AVR32_TC0, 0); } /** * \brief Application main routine */ int main(void) { board_init(); sysclk_init(); irq_initialize_vectors(); cpu_irq_enable(); pwm_timer_init(); touch_init(); while (true) { touch_handler(); } }
/** * \name PWM functions * @{ */ void ui_pwm_led_init(uint8_t lednum) { /* Timer waveform options */ static tc_waveform_opt_t waveform_options = { /* Channel selection. */ .channel = 1, .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, .acpc = TC_EVT_EFFECT_NOOP, .acpa = TC_EVT_EFFECT_NOOP, /* Waveform selection */ .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, /* External event trigger enable. */ .enetrg = false, /* External event selection (non-zero for Channel B to work) */ .eevt = !0, /* External event edge selection. */ .eevtedg = TC_SEL_NO_EDGE, .cpcdis = false, .cpcstop = false, .burst = false, .clki = false, /* Internal source clock 5, fPBA/128. */ .tcclks = TC_CLOCK_SOURCE_TC5, }; switch (lednum) { case LED0: /* Assign output pin to timer/counter 0 channel A */ /* Channel selection. */ waveform_options.channel = 1; waveform_options.bcpc = TC_EVT_EFFECT_NOOP; waveform_options.bcpb = TC_EVT_EFFECT_NOOP; /* RC compare effect on TIOA. */ waveform_options.acpc = TC_EVT_EFFECT_CLEAR; /* RA compare effect on TIOA. */ waveform_options.acpa = TC_EVT_EFFECT_SET; /* Setup timer/counter waveform mode */ sysclk_enable_peripheral_clock(&AVR32_TC0); tc_init_waveform(&AVR32_TC0, &waveform_options); /* Write the TOP (RC) and COMPARE (RA) values */ tc_write_ra(&AVR32_TC0, 1, 1); /* Set RA value. */ tc_write_rc(&AVR32_TC0, 1, 255); /* Set RC value. */ /* Start the timer PWM channel */ tc_start(&AVR32_TC0, 1); break; case LED1: /* Assign output pin to timer/counter 1 channel B */ /* Channel selection. */ waveform_options.channel = 2; waveform_options.acpc = TC_EVT_EFFECT_NOOP; waveform_options.acpa = TC_EVT_EFFECT_NOOP; /* RC compare effect on TIOB. */ waveform_options.bcpc = TC_EVT_EFFECT_CLEAR; /* RB compare effect on TIOB. */ waveform_options.bcpb = TC_EVT_EFFECT_SET; /* Setup timer/counter waveform mode */ sysclk_enable_peripheral_clock(&AVR32_TC1); tc_init_waveform(&AVR32_TC1, &waveform_options); /* Write the TOP (RC) and COMPARE (RB) values */ tc_write_rb(&AVR32_TC1, 2, 1); /* Set RB value. */ tc_write_rc(&AVR32_TC1, 2, 255); /* Set RC value. */ /* Start the timer PWM channel */ tc_start(&AVR32_TC1, 2); break; default: break; } } void ui_pwm_update(uint8_t channum, uint8_t brightness) { switch (channum) { case LED0: if (brightness != 0) { gpio_enable_module_pin(AVR32_TC0_A1_0_1_PIN, AVR32_TC0_A1_0_1_FUNCTION); tc_start(&AVR32_TC0, 1); tc_write_ra(&AVR32_TC0, 1, brightness); } else { tc_stop(&AVR32_TC0, 1); LED_Off(LED0); } break; case LED1: if (brightness != 0) { gpio_enable_module_pin(AVR32_TC1_B2_0_PIN, AVR32_TC1_B2_0_FUNCTION); tc_start(&AVR32_TC1, 2); tc_write_rb(&AVR32_TC1, 2, brightness); } else { tc_stop(&AVR32_TC1, 2); LED_Off(LED0); } break; default: break; } } /* End of PWM */ /** @} */ /** * \name Display functions * @{ */ static void ui_display_enable(void) { delay_init(sysclk_get_cpu_hz()); et024006_Init( sysclk_get_cpu_hz(), sysclk_get_hsb_hz()); /* Clear the display i.e. make it black */ et024006_DrawFilledRect(0, 0, ET024006_WIDTH, ET024006_HEIGHT, BLACK ); /* Set the backlight. */ gpio_set_gpio_pin(ET024006DHU_BL_PIN); ui_display_init_rtc(); ui_display_welcome_msg(); }
void PWM_timer_init(void) { //MUST CHANGE BACK!!!!! collective = 100; yaw = 0; pitch = 0; roll = 0; t_a = 0; t_b = 0; t_c = 0; t_r = 0; //Set up the GPIO pins for output of the timers gpio_enable_module_pin(AVR32_TC1_A2_0_PIN, AVR32_TC1_A2_0_FUNCTION); gpio_enable_module_pin(AVR32_TC1_B0_0_PIN, AVR32_TC1_B0_0_FUNCTION); gpio_enable_module_pin(AVR32_TC1_B1_0_PIN, AVR32_TC1_B1_0_FUNCTION); gpio_enable_module_pin(AVR32_TC0_B2_0_PIN, AVR32_TC0_B2_0_FUNCTION); gpio_enable_module_pin(AVR32_TC0_B0_0_0_PIN, AVR32_TC0_B0_0_0_FUNCTION); // Timer waveform options const tc_waveform_opt_t waveform_options_b0_1 = { //! Channel selection. .channel = 0, //! Software trigger effect on TIOB. .bswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOB. .beevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOB. .bcpc = TC_EVT_EFFECT_CLEAR, //! RB compare effect on TIOB. .bcpb = TC_EVT_EFFECT_SET, //! Software trigger effect on TIOA. .aswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOA. .aeevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOA. .acpc = TC_EVT_EFFECT_NOOP, //! RA compare effect on TIOA. .acpa = TC_EVT_EFFECT_NOOP, //! Waveform selection .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, //! External event trigger enable. .enetrg = false, //! External event selection (non-zero for Channel B to work) .eevt = !0, //! External event edge selection. .eevtedg = TC_SEL_NO_EDGE, //! Counter disable when RC compare. .cpcdis = false, //! Counter clock stopped with RC compare. .cpcstop = false, //! Burst signal selection. .burst = false, //! Clock inversion selection. .clki = false, //! Internal source clock 5, fPBA/128. .tcclks = TC_CLOCK_SOURCE_TC4, }; const tc_waveform_opt_t waveform_options_b0_0 = { //! Channel selection. .channel = 0, //! Software trigger effect on TIOB. .bswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOB. .beevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOB. .bcpc = TC_EVT_EFFECT_CLEAR, //! RB compare effect on TIOB. .bcpb = TC_EVT_EFFECT_SET, //! Software trigger effect on TIOA. .aswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOA. .aeevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOA. .acpc = TC_EVT_EFFECT_NOOP, //! RA compare effect on TIOA. .acpa = TC_EVT_EFFECT_NOOP, //! Waveform selection .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, //! External event trigger enable. .enetrg = false, //! External event selection (non-zero for Channel B to work) .eevt = !0, //! External event edge selection. .eevtedg = TC_SEL_NO_EDGE, //! Counter disable when RC compare. .cpcdis = false, //! Counter clock stopped with RC compare. .cpcstop = false, //! Burst signal selection. .burst = false, //! Clock inversion selection. .clki = false, //! Internal source clock 5, fPBA/128. .tcclks = TC_CLOCK_SOURCE_TC4, }; const tc_waveform_opt_t waveform_options_b1 = { //! Channel selection. .channel = 1, //! Software trigger effect on TIOB. .bswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOB. .beevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOB. .bcpc = TC_EVT_EFFECT_CLEAR, //! RB compare effect on TIOB. .bcpb = TC_EVT_EFFECT_SET, //! Software trigger effect on TIOA. .aswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOA. .aeevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOA. .acpc = TC_EVT_EFFECT_NOOP, //! RA compare effect on TIOA. .acpa = TC_EVT_EFFECT_NOOP, //! Waveform selection .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, //! External event trigger enable. .enetrg = false, //! External event selection (non-zero for Channel B to work) .eevt = !0, //! External event edge selection. .eevtedg = TC_SEL_NO_EDGE, //! Counter disable when RC compare. .cpcdis = false, //! Counter clock stopped with RC compare. .cpcstop = false, //! Burst signal selection. .burst = false, //! Clock inversion selection. .clki = false, //! Internal source clock 5, fPBA/128. .tcclks = TC_CLOCK_SOURCE_TC4, }; const tc_waveform_opt_t waveform_options_b2 = { //! Channel selection. .channel = 2, //! Software trigger effect on TIOB. .bswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOB. .beevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOB. .bcpc = TC_EVT_EFFECT_CLEAR, //! RB compare effect on TIOB. .bcpb = TC_EVT_EFFECT_SET, //! Software trigger effect on TIOA. .aswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOA. .aeevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOA. .acpc = TC_EVT_EFFECT_CLEAR, //! RA compare effect on TIOA. .acpa = TC_EVT_EFFECT_SET, //! Waveform selection .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, //! External event trigger enable. .enetrg = false, //! External event selection (non-zero for Channel B to work) .eevt = !0, //! External event edge selection. .eevtedg = TC_SEL_NO_EDGE, //! Counter disable when RC compare. .cpcdis = false, //! Counter clock stopped with RC compare. .cpcstop = false, //! Burst signal selection. .burst = false, //! Clock inversion selection. .clki = false, //! Internal source clock 5, fPBA/128. .tcclks = TC_CLOCK_SOURCE_TC4, }; const tc_waveform_opt_t waveform_options_a2 = { //! Channel selection. .channel = 2, //! Software trigger effect on TIOB. .bswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOB. .beevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOB. .bcpc = TC_EVT_EFFECT_NOOP, //! RB compare effect on TIOB. .bcpb = TC_EVT_EFFECT_NOOP, //! Software trigger effect on TIOA. .aswtrg = TC_EVT_EFFECT_NOOP, //! External event effect on TIOA. .aeevt = TC_EVT_EFFECT_NOOP, //! RC compare effect on TIOA. .acpc = TC_EVT_EFFECT_CLEAR, //! RA compare effect on TIOA. .acpa = TC_EVT_EFFECT_SET, //! Waveform selection .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, //! External event trigger enable. .enetrg = false, //! External event selection (non-zero for Channel B to work) .eevt = !0, //! External event edge selection. .eevtedg = TC_SEL_NO_EDGE, //! Counter disable when RC compare. .cpcdis = false, //! Counter clock stopped with RC compare. .cpcstop = false, //! Burst signal selection. .burst = false, //! Clock inversion selection. .clki = false, //! Internal source clock 5, fPBA/128. .tcclks = TC_CLOCK_SOURCE_TC4, }; // Setup timer/counter waveform mode sysclk_enable_peripheral_clock(&AVR32_TC0); sysclk_enable_peripheral_clock(&AVR32_TC1); tc_init_waveform(&AVR32_TC1, &waveform_options_b1); tc_init_waveform(&AVR32_TC1, &waveform_options_b0_1); tc_init_waveform(&AVR32_TC1, &waveform_options_a2); tc_init_waveform(&AVR32_TC0, &waveform_options_b0_0); tc_init_waveform(&AVR32_TC0, &waveform_options_b2); tc_write_rb(&AVR32_TC1, 0, B_BASE); tc_write_rc(&AVR32_TC1, 0, RC_VAL); tc_write_rb(&AVR32_TC1, 1, R_BASE); tc_write_rc(&AVR32_TC1, 1, RC_VAL); tc_write_ra(&AVR32_TC1, 2, A_BASE); tc_write_rc(&AVR32_TC1, 2, RC_VAL); tc_write_rb(&AVR32_TC0, 0, M_BASE); tc_write_rc(&AVR32_TC0, 0, RC_VAL); tc_write_rb(&AVR32_TC0, 2, C_BASE); tc_write_rc(&AVR32_TC0, 2, RC_VAL); // Start the timer PWM channels tc_start(&AVR32_TC1, 2); tc_start(&AVR32_TC1, 0); tc_start(&AVR32_TC1, 1); tc_start(&AVR32_TC0, 0); tc_start(&AVR32_TC0, 2); } void PWM_tester(char servo, int delay){ int initial_delay = 2000; if(servo=='a'){ for(int i=0;i<=O_MAX;i++){ tc_write_ra(&AVR32_TC1, 2, A_BASE-i); if(i==0) delay_ms(initial_delay); else delay_ms(delay); } } else if(servo=='b'){ for(int i=0;i<=O_MAX;i++){ tc_write_rb(&AVR32_TC1, 0, B_BASE+i); if(i==0) delay_ms(initial_delay); else delay_ms(delay); } } else if(servo=='c'){ for(int i=0;i<=O_MAX;i++){ tc_write_rb(&AVR32_TC0, 2, C_BASE-i); if(i==0) delay_ms(initial_delay); else delay_ms(delay); } } else if(servo=='r'){ for(int i=0;i<=R_MAX;i++){ tc_write_rb(&AVR32_TC1, 1, R_BASE+i); if(i==0) delay_ms(initial_delay); else delay_ms(delay); } } else if(servo=='e'){ for(int i=0;i<O_MAX;i++){ tc_write_ra(&AVR32_TC1, 2, A_BASE-i); tc_write_rb(&AVR32_TC1, 0, B_BASE+i); tc_write_rb(&AVR32_TC0, 2, C_BASE-i); if(i<R_MAX) tc_write_rb(&AVR32_TC1, 1, R_BASE+i); //tc_write_rb(&AVR32_TC0, 0, 255); if(i==0) delay_ms(3000); else delay_ms(delay); } } } void PWM_update(void){ //gpio_toggle_pin(LED1_GPIO); t_a = collective-pitch+roll; t_b = collective-pitch-roll; t_c = collective+pitch+pitch; t_r = yaw+100; //if(collective!=0 || yaw !=0 || pitch!=0 || roll !=0) gpio_toggle_pin(LED0_GPIO); check_max_values(); tc_write_ra(&AVR32_TC1, 2, A_BASE-t_a); tc_write_rb(&AVR32_TC1, 0, B_BASE+t_b); tc_write_rb(&AVR32_TC0, 2, C_BASE-t_c); tc_write_rb(&AVR32_TC1, 1, R_BASE+t_r); } void set_motor(char setting){ int level = (int) setting; if(level>100) level = 100; level = (int)(level * 3.75f); tc_write_rb(&AVR32_TC0, 0, M_BASE - level); motor = level; } int get_servo_dat(char servo){ switch(servo){ case 'a': return t_a; break; case 'b': return t_b; break; case 'c': return t_c; break; case 'r': return t_r; break; case 'o': return collective; break; case 'y': return yaw; break; case 'p': return pitch; break; case 'l': return roll; break; case 'm': return motor; break; default: return 0; break; } } void check_max_values(void){ if(t_a>=O_MAX) t_a = O_MAX; else if(t_a<0) t_a = 0; if(t_b>=O_MAX) t_b = O_MAX; else if(t_b<0) t_b = 0; if(t_c>=O_MAX) t_c = O_MAX; else if(t_c<0) t_c = 0; if(t_r>=R_MAX) t_r = R_MAX; else if(t_r<0) t_r = 0; } void set_PWM_dat(int16_t* PWM_dat, char where){ /* [0] = packet type [1] = collective [2] = yaw [3] = pitch [4] = roll */ //gpio_toggle_pin(LED2_GPIO); switch (where){ case 'm': collective = (int8_t)PWM_dat[1]; yaw = (int8_t)PWM_dat[2]; pitch = (int8_t)PWM_dat[3]; roll = (int8_t)PWM_dat[4]; break; default: collective = PWM_dat[0]; yaw = PWM_dat[1]; pitch = PWM_dat[2]; roll = PWM_dat[3]; break; } check_orientation_values(); } void check_orientation_values(void){ if(pitch>MAX_PITCH) pitch = MAX_PITCH; else if(pitch<-MAX_PITCH) pitch = -MAX_PITCH; if(roll>MAX_ROLL) roll = MAX_ROLL; else if(roll<-MAX_ROLL) roll = -MAX_ROLL; if(yaw>MAX_YAW) yaw = MAX_YAW; else if(yaw<-MAX_YAW) yaw = -MAX_YAW; }