// // hello.speaker.45.c // // speaker PWM hello-world // // Neil Gershenfeld // 11/5/18 // // (c) Massachusetts Institute of Technology 2018 // This work may be reproduced, modified, distributed, // performed, and displayed for any purpose. Copyright is // retained and must be preserved. The work is provided // as is; no warranty is provided, and users accept all // liability. // #include #include #define output(directions,pin) (directions |= pin) // set port direction for output #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define cycle_delay _delay_us(10) // 10 us cycle delay time #define pmin 25 // minimum half period, in cycle delays #define pmax 500 // maximum half period #define pstep 0.95 // half period step factor #define duration 1000 // period step duration #define amin 100 // minumum amplitude, in PWM units #define amax 200 // maximum amplitude #define astep 50 // amplitude step #define off 255 // amplitude off #define MOSFET_pin (1 << PB1) #define MOSFET_port PORTB #define MOSFET_direction DDRB int main(void) { // // main // static uint16_t frequency,period,cycle,cycles,delays; static uint8_t amplitude; // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // // TCCR0A = ((1 << COM0B0) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00)); // set OC0B on compare match and set fast PWM mode, 0xFF TOP TCCR0B = (1 << CS00); // set timer 0 prescalar to 1 // // initialize MOSFET pin // clear(MOSFET_port, MOSFET_pin); output(MOSFET_direction, MOSFET_pin); // // main loop // while (1) { // // loop over amplitudes // for (amplitude = amax; amplitude >= amin; amplitude -= astep) { // // loop over periods // for (period = pmax; period >= pmin; period *= pstep) { // // loop over square wave cycles // cycles = duration/period; for (cycle = 0; cycle < cycles; ++cycle) { // // set PWM current on // OCR0B = amplitude; // // loop over delay // for (delays = 0; delays < period; ++delays) cycle_delay; // // set PWM current off // OCR0B = off; // // loop over delay // for (delays = 0; delays < period; ++delays) cycle_delay; } } } } }