dig:mic-servo
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Previous revisionNext revision | |||
— | dig:mic-servo [2011/03/22 14:56] – tobi | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | Here are the main.c and mic-servo.py code for a working project for [[lab_3]]. | ||
+ | |||
+ | ==== main.c ==== | ||
+ | |||
+ | <code c> | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | // RGG LED main.c | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | //#include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | #if USB_DEVICE_FEATURE == ENABLED | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #endif | ||
+ | |||
+ | // RGB LED and servo PWM defines | ||
+ | |||
+ | #define cR 0 | ||
+ | #define cG 1 | ||
+ | #define cB 2 | ||
+ | #define cServo 3 // indexes into channel arrays | ||
+ | |||
+ | #define R_PWM_PIN AVR32_PWM_1_0_PIN | ||
+ | #define R_PWM_FUNCTION AVR32_PWM_1_0_FUNCTION | ||
+ | #define R_PWM_CHANNEL_ID 1 | ||
+ | |||
+ | // note we skip PWM[2]=pin 25 because it is used by default fuse settings and DFU bootloader code as DFU launcher input pin | ||
+ | #define G_PWM_PIN AVR32_PWM_3_0_PIN // PA14 | ||
+ | #define G_PWM_FUNCTION AVR32_PWM_3_0_FUNCTION | ||
+ | #define G_PWM_CHANNEL_ID 3 | ||
+ | |||
+ | #define B_PWM_PIN AVR32_PWM_4_0_PIN // PA15 | ||
+ | #define B_PWM_FUNCTION AVR32_PWM_4_0_FUNCTION | ||
+ | #define B_PWM_CHANNEL_ID 4 | ||
+ | |||
+ | static pwm_opt_t pwm_opt; | ||
+ | static avr32_pwm_channel_t pwm_channel[4]; | ||
+ | static unsigned int channel_id[4]; | ||
+ | |||
+ | #define TTT 4 // defines how to multiply PWM period and duty cycle values for the RGB LED PWM channels. | ||
+ | |||
+ | // Timer / Counter, used to generate interrupt for ADC sampling | ||
+ | |||
+ | # define EXAMPLE_TC | ||
+ | # define EXAMPLE_TC_IRQ_GROUP | ||
+ | # define EXAMPLE_TC_IRQ | ||
+ | # define FPBA FOSC0 // chosen PBA clock frequency - set up to be same as cystral freq=12MHz | ||
+ | #define FADC 10000 // desired ADC sample rate in Hz | ||
+ | #define TC_CHANNEL | ||
+ | volatile U32 tc_tick = 0; // counts samples | ||
+ | volatile bool takeSampleNow=TRUE; | ||
+ | int dspCounter=0; | ||
+ | |||
+ | // adc | ||
+ | #define ADC_CHANNEL | ||
+ | #define ADC_PIN | ||
+ | #define ADC_FUNCTION | ||
+ | |||
+ | // Signal processing: | ||
+ | long audMean=0; // holds mean mic signal, for high pass filtering | ||
+ | long meanSq=0; // holds mean square audio signal | ||
+ | long maxSq=0; // holds max, for clipping detection | ||
+ | unsigned int servo; // the computed servo signal, ranging from 1000-2000 us | ||
+ | bool initialized=0; | ||
+ | #define NTAU1 6 // 'time constant' | ||
+ | #define TAU2 64 // 'time constant' | ||
+ | |||
+ | // servo | ||
+ | #define FSERVOUPDATE 100 // update rate for servo pulse width in main loop in Hz | ||
+ | #define SERVO_PIN AVR32_PWM_6_0_PIN // PWM_6_0 is PA19 | ||
+ | #define SERVO_PWM_FUNCTION AVR32_PWM_6_0_FUNCTION | ||
+ | |||
+ | #define SERVO_PWM_CHANNEL_ID 6 | ||
+ | #define SERVO_MID 773 // counts to get 1500us pulse width | ||
+ | #define SERVO_MULT 0.5156 // for static calculations; | ||
+ | |||
+ | // USB | ||
+ | static U32 sof_cnt; // start-of-frame counts, get one every ms | ||
+ | static U8 in_data_length; | ||
+ | static U8 in_buf[EP_SIZE_TEMP1]; | ||
+ | static U8 out_data_length; | ||
+ | static U8 out_buf[EP_SIZE_TEMP2]; | ||
+ | |||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | // clock setup | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | #define FOSC0 | ||
+ | #define OSC0_STARTUP | ||
+ | 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, | ||
+ | // 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(& | ||
+ | |||
+ | // Setup PLL0 on Osc0, mul=10 ,no divisor, lockcount=16: | ||
+ | pm_pll_setup(& | ||
+ | 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(& | ||
+ | 1, // pll_freq. | ||
+ | 1, // pll_div2. | ||
+ | 0); // pll_wbwdisable. | ||
+ | // Enable the PLL. | ||
+ | pm_pll_enable(& | ||
+ | // Wait until the PLL output is stable. | ||
+ | pm_wait_for_pll0_locked(& | ||
+ | // Configure each clock domain to use the main clock divided by 2 | ||
+ | // => fCPU = fPBA = fPBB = 33MHz. | ||
+ | pm_cksel(& | ||
+ | 0, // pbasel. | ||
+ | 1, // pbbdiv. | ||
+ | 0, // pbbsel. | ||
+ | 1, // hsbdiv=cpudiv | ||
+ | 0); // hsbsel=cpusel | ||
+ | // Switch the main clock source to PLL0. | ||
+ | pm_switch_to_clock(& | ||
+ | } | ||
+ | |||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | // PWM setup | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | // PWM setup | ||
+ | void init_pwm() { | ||
+ | |||
+ | // set PWM GPIOs | ||
+ | gpio_enable_module_pin(R_PWM_PIN, | ||
+ | gpio_enable_module_pin(G_PWM_PIN, | ||
+ | gpio_enable_module_pin(B_PWM_PIN, | ||
+ | gpio_enable_module_pin(SERVO_PIN, | ||
+ | |||
+ | // PWM controller configuration. | ||
+ | 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; | ||
+ | // init pwm globals | ||
+ | pwm_init(& | ||
+ | |||
+ | channel_id[cR] = R_PWM_CHANNEL_ID; | ||
+ | channel_id[cG] = G_PWM_CHANNEL_ID; | ||
+ | channel_id[cB] = B_PWM_CHANNEL_ID; | ||
+ | channel_id[cServo] = SERVO_PWM_CHANNEL_ID; | ||
+ | |||
+ | // the core runs at 33MHz (see init_clock()). Therefore we get PWM base clock of 33Mhz. | ||
+ | // Then we divide this down by powers of 2 and supply 20 bit count values for the period and duty cycle. | ||
+ | // We observe that the LED frequency is 4kHz. | ||
+ | // The LED channels are set up to use 33 MHz/2 clock source, and count to 256<< | ||
+ | // Therefore we expect that the frequency is 33M/ | ||
+ | |||
+ | // To get a reasonable servo pulse frequency of 200Hz, we use for the servo channel a further division by 32 to get | ||
+ | // a frequency of 4.028kHz/ | ||
+ | |||
+ | unsigned int c; | ||
+ | for (c = cR; c <= cB; c++) { | ||
+ | |||
+ | pwm_channel[c].CMR.calg = PWM_MODE_LEFT_ALIGNED; | ||
+ | pwm_channel[c].CMR.cpol = PWM_POLARITY_HIGH; | ||
+ | pwm_channel[c].CMR.cpd = PWM_UPDATE_DUTY; | ||
+ | pwm_channel[c].CMR.cpre = AVR32_PWM_CPRE_MCK_DIV_2; | ||
+ | pwm_channel[c].cdty = 0; // Channel duty cycle, should be < CPRD. | ||
+ | pwm_channel[c].cprd = (256 << TTT); // Channel period. | ||
+ | pwm_channel[c].cupd = 0; // Channel update is not used here. | ||
+ | |||
+ | pwm_channel_init(channel_id[c], | ||
+ | } | ||
+ | |||
+ | // servo channel | ||
+ | // the duty cycle units here are in units of the prescaled clock period which is 64/ | ||
+ | // Therefore to get X us we need to supply X/1.939 counts to cdty, or approximately X/2 counts. | ||
+ | // Therefore to get 1500us we need to supply 773 counts or about 750 counts. | ||
+ | |||
+ | pwm_channel[cServo].CMR.calg = PWM_MODE_LEFT_ALIGNED; | ||
+ | pwm_channel[cServo].CMR.cpol = PWM_POLARITY_HIGH; | ||
+ | pwm_channel[cServo].CMR.cpd = PWM_UPDATE_DUTY; | ||
+ | pwm_channel[cServo].CMR.cpre = AVR32_PWM_CPRE_MCK_DIV_64; | ||
+ | pwm_channel[cServo].cdty = 0; // start at zero to leave servo disabled if it was disabled and is digital servo with annoying whine. // SERVO_MID; // Channel duty cycle, should be < CPRD. | ||
+ | pwm_channel[cServo].cprd = (256 << TTT); // Channel period. | ||
+ | pwm_channel[cServo].cupd = 0; // Channel update is not used here. | ||
+ | |||
+ | pwm_channel_init(channel_id[cServo], | ||
+ | |||
+ | pwm_start_channels((1 << channel_id[cR]) | (1 << channel_id[cG]) | (1<< channel_id[cB])|(1<< | ||
+ | } | ||
+ | |||
+ | // sets RGB LED brightnesses, | ||
+ | void set_rgb(U8 r, U8 g, U8 b) { | ||
+ | U8 c; | ||
+ | for (c = cR; c <= cB; c++) { | ||
+ | // Channel duty cycle, should be < CPRD. | ||
+ | switch (c) { | ||
+ | case cR: | ||
+ | pwm_channel[c].cdty = ((U32) r) << TTT; | ||
+ | break; | ||
+ | case cG: | ||
+ | pwm_channel[c].cdty = ((U32) g) << TTT; | ||
+ | break; | ||
+ | case cB: | ||
+ | pwm_channel[c].cdty = ((U32) b) << TTT; | ||
+ | break; | ||
+ | } | ||
+ | pwm_channel_init(channel_id[c], | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Sets the pulse width for the servo output. | ||
+ | * Argument, pulse width in us from 1000 to 2000 | ||
+ | * | ||
+ | */ | ||
+ | void setServoPWUs(U16 us) { | ||
+ | pwm_channel[cServo].cdty = ((U32) us>> | ||
+ | pwm_channel_init(channel_id[cServo], | ||
+ | } | ||
+ | |||
+ | |||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | // ADC | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | // initializes ADC for one channel | ||
+ | void init_adc() { | ||
+ | // GPIO pin/ | ||
+ | static const gpio_map_t ADC_GPIO_MAP = { { ADC_PIN, ADC_FUNCTION } }; | ||
+ | |||
+ | volatile avr32_adc_t *adc = & | ||
+ | |||
+ | |||
+ | |||
+ | // Assign and enable GPIO pins to the ADC function. | ||
+ | gpio_enable_module(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). | ||
+ | // TODO These ADC config numbers are wrong currently! | ||
+ | AVR32_ADC.mr |= 0x3 << AVR32_ADC_MR_PRESCAL_OFFSET; | ||
+ | adc_configure(adc); | ||
+ | |||
+ | // Assign the on-board sensors to their ADC channel. | ||
+ | unsigned short adc_channel = ADC_CHANNEL; | ||
+ | |||
+ | // Enable the ADC channels. | ||
+ | adc_enable(adc, | ||
+ | } | ||
+ | |||
+ | U16 get_adc_value() { | ||
+ | // launch conversion on all enabled channels | ||
+ | volatile avr32_adc_t *adc = & | ||
+ | adc_start(adc); | ||
+ | |||
+ | // get value for the adc channel | ||
+ | U16 adc_value = adc_get_value(adc, | ||
+ | |||
+ | return adc_value; | ||
+ | } | ||
+ | |||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | // USB | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | //! | ||
+ | //! @brief This function initializes the hardware/ | ||
+ | //! | ||
+ | void device_task_init(void) { | ||
+ | sof_cnt = 0; | ||
+ | in_data_length = 0; | ||
+ | out_data_length = 0; | ||
+ | |||
+ | Usb_enable_sof_interrupt();// | ||
+ | } | ||
+ | |||
+ | |||
+ | //! | ||
+ | //! @brief Entry point of the device applicative task management | ||
+ | //! | ||
+ | //! This function links the device application to the USB bus. | ||
+ | //! | ||
+ | void device_task(void) { | ||
+ | |||
+ | if (takeSampleNow) { // flag set in timer ISR | ||
+ | gpio_local_tgl_gpio_pin(AVR32_PIN_PA11); | ||
+ | takeSampleNow=FALSE; | ||
+ | // signal processing | ||
+ | S16 adcval = (S16)get_adc_value(); | ||
+ | |||
+ | if (initialized) | ||
+ | audMean = ((adcval-audMean)>> | ||
+ | else | ||
+ | audMean = adcval; // init filter with first reading | ||
+ | |||
+ | if(dspCounter--==0){ // only update meanSq at this interval, so to produce effective time constant that is TAU2 times tau of audMean filtering | ||
+ | dspCounter=TAU2; | ||
+ | long diff = adcval - audMean; // signed diff of sample from mean | ||
+ | long sq = diff * diff; // square diff | ||
+ | if (initialized) | ||
+ | meanSq = ((sq-meanSq)>> | ||
+ | else | ||
+ | meanSq = sq; | ||
+ | |||
+ | if (meanSq > maxSq) | ||
+ | maxSq = meanSq; // not used now | ||
+ | |||
+ | } | ||
+ | |||
+ | initialized = 1; | ||
+ | // we update the servo at FSERVOUPDATE frequency. | ||
+ | // and update the servo only every FADC/ | ||
+ | if (tc_tick % (FADC / FSERVOUPDATE) == 0) { | ||
+ | servo = (unsigned int) (meanSq >> 3); // send meanSq back to host | ||
+ | |||
+ | if (servo > 2000) | ||
+ | servo = 2000; | ||
+ | else if (servo < 1000) | ||
+ | servo = 1000; | ||
+ | |||
+ | setServoPWUs(servo); | ||
+ | // only communicate if we are enumerated | ||
+ | if (!Is_device_enumerated()) | ||
+ | return; | ||
+ | |||
+ | // HERE STARTS THE USB DEVICE APPLICATIVE CODE | ||
+ | |||
+ | // Load the IN endpoint (to the host PC) with the desired measurement to show on host | ||
+ | if (Is_usb_in_ready(EP_TEMP_IN)) { | ||
+ | |||
+ | // store bytes of 32 bit value to buffer...: | ||
+ | in_buf[0] = 0xFF & (meanSq>> | ||
+ | in_buf[1] = 0xff & (meanSq>> | ||
+ | in_buf[2] = 0xFF & (meanSq >> 8); | ||
+ | in_buf[3] = 0xFF & (meanSq >> 0); | ||
+ | in_data_length = 4; | ||
+ | |||
+ | // do magic to send the packet | ||
+ | Usb_reset_endpoint_fifo_access(EP_TEMP_IN); | ||
+ | usb_write_ep_txpacket(EP_TEMP_IN, | ||
+ | in_data_length = 0; | ||
+ | Usb_ack_in_ready_send(EP_TEMP_IN); | ||
+ | |||
+ | } | ||
+ | |||
+ | // If we receive something in the OUT endpoint (from the host), use it to set the RGB color | ||
+ | if (Is_usb_out_received(EP_TEMP_OUT)) { | ||
+ | gpio_local_tgl_gpio_pin(AVR32_PIN_PA12); | ||
+ | |||
+ | Usb_reset_endpoint_fifo_access(EP_TEMP_OUT); | ||
+ | out_data_length = Usb_byte_count(EP_TEMP_OUT); | ||
+ | usb_read_ep_rxpacket(EP_TEMP_OUT, | ||
+ | Usb_ack_out_received_free(EP_TEMP_OUT); | ||
+ | |||
+ | // update PWM: | ||
+ | set_rgb(out_buf[1], | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | //! | ||
+ | //! @brief usb_sof_action | ||
+ | //! | ||
+ | //! This function increments the sof_cnt counter each time | ||
+ | //! the USB Start-of-Frame interrupt subroutine is executed (1 ms). | ||
+ | //! Useful to manage time delays | ||
+ | //! | ||
+ | void usb_sof_action(void) { | ||
+ | // | ||
+ | sof_cnt++; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | /*! \brief TC interrupt - used for AD conversion. | ||
+ | */ | ||
+ | #if defined (__GNUC__) | ||
+ | __attribute__((__interrupt__)) | ||
+ | #elif defined (__ICCAVR32__) | ||
+ | #pragma handler = EXAMPLE_TC_IRQ_GROUP, | ||
+ | __interrupt | ||
+ | #endif | ||
+ | static void tc_irq(void) { | ||
+ | // Increment the counter, which is also used to determine servo updates | ||
+ | tc_tick++; | ||
+ | |||
+ | // set a flag to tell main loop to take a sample | ||
+ | takeSampleNow = TRUE; | ||
+ | |||
+ | // Clear the interrupt flag. This is a side effect of reading the TC SR. | ||
+ | tc_read_sr(EXAMPLE_TC, | ||
+ | |||
+ | // Toggle a GPIO pin (this pin is used as a regular GPIO pin). | ||
+ | gpio_local_tgl_gpio_pin(AVR32_PIN_PA10); | ||
+ | } | ||
+ | |||
+ | void init_tc(){ | ||
+ | // Timer/ | ||
+ | static const tc_waveform_opt_t WAVEFORM_OPT = | ||
+ | { | ||
+ | .channel | ||
+ | |||
+ | .bswtrg | ||
+ | .beevt | ||
+ | .bcpc = TC_EVT_EFFECT_NOOP, | ||
+ | .bcpb = TC_EVT_EFFECT_NOOP, | ||
+ | |||
+ | .aswtrg | ||
+ | .aeevt | ||
+ | .acpc = TC_EVT_EFFECT_NOOP, | ||
+ | .acpa = TC_EVT_EFFECT_NOOP, | ||
+ | |||
+ | .wavsel | ||
+ | .enetrg | ||
+ | .eevt = 0, // External event selection. | ||
+ | .eevtedg | ||
+ | .cpcdis | ||
+ | .cpcstop | ||
+ | |||
+ | .burst | ||
+ | .clki = FALSE, | ||
+ | .tcclks | ||
+ | }; | ||
+ | |||
+ | //! Timer/ | ||
+ | static const tc_interrupt_t TC_INTERRUPT = | ||
+ | { | ||
+ | .etrgs = 0, //! External trigger interrupt. | ||
+ | .ldrbs = 0, //! RB load interrupt. | ||
+ | .ldras = 0, //! RA load interrupt. | ||
+ | .cpcs = 1, //! RC compare interrupt. | ||
+ | .cpbs = 0, //! RB compare interrupt. | ||
+ | .cpas = 0, //! RA compare interrupt. | ||
+ | .lovrs = 0, //! Load overrun interrupt. | ||
+ | .covfs = 0 //! Counter overflow interrupt. | ||
+ | }; | ||
+ | |||
+ | |||
+ | volatile avr32_tc_t *tc = EXAMPLE_TC; | ||
+ | Disable_global_interrupt(); | ||
+ | |||
+ | // Register the RTC interrupt handler to the interrupt controller. | ||
+ | INTC_register_interrupt(& | ||
+ | |||
+ | Enable_global_interrupt(); | ||
+ | |||
+ | // Initialize the timer/ | ||
+ | tc_init_waveform(tc, | ||
+ | |||
+ | // Set the compare triggers for timer/ | ||
+ | // TC counter is 16-bits, with secondary main clock fPBA = 12 MHz. | ||
+ | // Lowest possible freq is 12e6/ | ||
+ | // We want ADC sample rate of FADC Hz. To get this, we load RC (Reset Counter) value so that | ||
+ | // TC reaches RC value every 1/FADC ms. Therefore we configure TC so that RC=FPBA/ | ||
+ | // E.g., to get FADC=10kHz, we need RC=12e6/ | ||
+ | tc_write_rc(tc, | ||
+ | |||
+ | tc_configure_interrupts(tc, | ||
+ | |||
+ | // Start the timer/ | ||
+ | tc_start(tc, | ||
+ | |||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | // main | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | |||
+ | |||
+ | int main() { | ||
+ | Enable_global_exception(); | ||
+ | |||
+ | Disable_global_interrupt(); | ||
+ | INTC_init_interrupts(); | ||
+ | |||
+ | pcl_switch_to_osc(PCL_OSC0, | ||
+ | |||
+ | init_clock(); | ||
+ | init_pwm(); | ||
+ | gpio_local_init(); | ||
+ | |||
+ | init_adc(); | ||
+ | |||
+ | pcl_configure_usb_clock(); | ||
+ | |||
+ | usb_task_init(); | ||
+ | init_tc(); | ||
+ | |||
+ | #if USB_DEVICE_FEATURE == ENABLED | ||
+ | device_task_init(); | ||
+ | #endif | ||
+ | |||
+ | gpio_local_enable_pin_output_driver(AVR32_PIN_PA10); | ||
+ | gpio_local_enable_pin_output_driver(AVR32_PIN_PA11); | ||
+ | gpio_local_enable_pin_output_driver(AVR32_PIN_PA12); | ||
+ | |||
+ | gpio_local_clr_gpio_pin(AVR32_PIN_PA10); | ||
+ | gpio_local_clr_gpio_pin(AVR32_PIN_PA11); | ||
+ | gpio_local_clr_gpio_pin(AVR32_PIN_PA12); | ||
+ | |||
+ | while (TRUE) { | ||
+ | usb_task(); | ||
+ | |||
+ | #if USB_DEVICE_FEATURE == ENABLED | ||
+ | device_task(); | ||
+ | #endif | ||
+ | } | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | // EOF | ||
+ | ////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ==== mic-servo.py ==== | ||
+ | |||
+ | |||
+ | <code python mic-servo.py> | ||
+ | # | ||
+ | |||
+ | import sys, os | ||
+ | import array | ||
+ | import usb | ||
+ | import colorsys | ||
+ | import time | ||
+ | import math | ||
+ | |||
+ | busses = usb.busses() | ||
+ | |||
+ | |||
+ | VENDOR = 0x03eb | ||
+ | PRODUCT = 0x2300 | ||
+ | IFACE = 0 | ||
+ | EP_IN = 0x81 | ||
+ | EP_OUT = 0x02 | ||
+ | |||
+ | |||
+ | deltah = 0.0003 | ||
+ | T = 0.00 | ||
+ | PWMperADC = 100 | ||
+ | BAR = 80 | ||
+ | |||
+ | tstart = time.time() | ||
+ | |||
+ | def get_device(): | ||
+ | for bus in busses: | ||
+ | devices = bus.devices | ||
+ | for dev in devices: | ||
+ | if dev.idVendor == VENDOR and dev.idProduct == PRODUCT: | ||
+ | return dev | ||
+ | return None | ||
+ | |||
+ | |||
+ | vmax = 1 | ||
+ | vmin = 2**16 | ||
+ | vavg=0.0 | ||
+ | vms=0.0 | ||
+ | m=.02 # mixing factor for filter | ||
+ | vavg=0.0 | ||
+ | initialized=False | ||
+ | vol=0 | ||
+ | |||
+ | def adc(v): | ||
+ | global vmax, vmin, m, vavg, vms, initialized, | ||
+ | |||
+ | vol=v | ||
+ | | ||
+ | if vol > vmax: vmax = vol | ||
+ | if vol < vmin: vmin = vol | ||
+ | if vmax <= vmin: vmin -= 1 | ||
+ | |||
+ | t = time.time() - tstart | ||
+ | hz = usbiocnt / t | ||
+ | |||
+ | |||
+ | # vol=int(255*(vol - vmin) / (vmax - vmin) ) | ||
+ | o = '% 4d Hz ' % hz | ||
+ | o+= '% 4d ' % vol | ||
+ | o += '#' | ||
+ | print o | ||
+ | |||
+ | |||
+ | usbiocnt = 0L | ||
+ | def usbio(dh): | ||
+ | global usbiocnt, vol | ||
+ | usbiocnt += 1 | ||
+ | | ||
+ | dout = array.array(' | ||
+ | |||
+ | dout[0] = 0xFF & 0x00 | ||
+ | dout[1] = 0xFF & (vol) # red | ||
+ | dout[2] = 0xFF & (vol) # green | ||
+ | dout[3] = 0xFF & (vol) # blue | ||
+ | |||
+ | dh.bulkWrite(EP_OUT, | ||
+ | |||
+ | #if usbiocnt % PWMperADC == 0: | ||
+ | if 1: | ||
+ | |||
+ | din = dh.bulkRead(EP_IN, | ||
+ | l = len(din) | ||
+ | if l != 4: | ||
+ | print " | ||
+ | else: | ||
+ | if usbiocnt % PWMperADC == 0: | ||
+ | value=(din[0]<< | ||
+ | adc(value) | ||
+ | |||
+ | |||
+ | def intcol(v): | ||
+ | v = int(v*256) | ||
+ | if v > 255: v = 255 | ||
+ | if v < 0: v = 0 | ||
+ | return v | ||
+ | |||
+ | |||
+ | def micservo(dh): | ||
+ | global vol | ||
+ | |||
+ | while 1: | ||
+ | |||
+ | usbio(dh) | ||
+ | |||
+ | time.sleep(T) | ||
+ | |||
+ | |||
+ | def main(): | ||
+ | |||
+ | dev = get_device() | ||
+ | dh = dev.open() | ||
+ | dh.claimInterface(IFACE) | ||
+ | |||
+ | micservo(dh) | ||
+ | |||
+ | dh.releaseInterface() | ||
+ | del dh | ||
+ | return 0 | ||
+ | |||
+ | |||
+ | if __name__ == ' | ||
+ | sys.exit( main() ) | ||
+ | |||
+ | </ | ||
dig/mic-servo.txt · Last modified: 2024/02/29 07:28 by 127.0.0.1