This code is from project: Creative T20 speakers standby mode
delay.h
#ifndef _H_DELAY_ #define _H_DELAY_ #define nop() __asm__ __volatile__("nop") void delay_ms(unsigned short ms); void delay_us(unsigned short us); #endif
delay.c
#include "main.h" #include <util/delay.h> #include "delay.h" /****************************************************************************/ /* It is better to put a delay in the loop than provide high value to */ /* standard function, because the code will be smaller, */ /****************************************************************************/ void delay_ms(unsigned short ms) { while ( ms ) { ms--; _delay_ms(1); } } void delay_us(unsigned short us) { while ( us ) { us--; _delay_us(1); } }
main.h
#ifndef _H_MAIN_H #define _H_MAIN_H // This is wrong, should be 1MHz, and it could affect _delay_ms(). // You can change this in your device. I don't bother to // disassembly T20 again and upload fix on MCU, // because it works ok for me. #define F_CPU 8000000L // some usefeuul macros #define H(a,b) a |=(1<<(b)) #define L(a,b) a &=~(1<<(b)) #define IS(a,b) bit_is_set(a,b) #define BS(a,b) (a & (1<<(b))) #endif
main.c
#include "main.h" #include <avr/io.h> #include <avr/interrupt.h> #include "delay.h" #define DIMMER_LEVEL 0x0F #define ADC_LEVEL 5 // globals uint8_t dimmer = 0; uint8_t up = 1; uint8_t disable_sleep = 0; void turn_on(); void turn_off(); /****************************************************************************/ /* Interrupt handler. When button is pressed, this will happen. */ /****************************************************************************/ SIGNAL(SIG_INTERRUPT0) { // if sleep mode is off, switch // it on and blink led once if(disable_sleep) { disable_sleep = 0; OCR0A = 0xFF; OCR0A = 0x00; delay_ms(100); OCR0A = 0xFF; } else { // disable sleep mode and blink led twice disable_sleep = 1; OCR0A = 0xFF; OCR0A = 0x00; delay_ms(100); OCR0A = 0xFF; delay_ms(100); OCR0A = 0x00; delay_ms(100); OCR0A = 0xFF; turn_on(); } // be sure not to fire INT0 couple of times delay_ms(500); } /****************************************************************************/ /* Function changes led brightness to the max, sets PB1 to high state */ /* (shutdown pin from TPA3123 will be in high state). Turns dimmer off. */ /****************************************************************************/ void turn_on() { OCR0A = 0xFF; dimmer = 0; H(PORTB, PB1); } /****************************************************************************/ /* Opposite of function above: shuts down TPA3123 by forcing low state on */ /* shutdown pin and turns on led dimmer. */ /****************************************************************************/ void turn_off() { while(OCR0A-- > DIMMER_LEVEL) { delay_ms(1); } up = 0; dimmer = 1; L(PORTB, PB1); } /****************************************************************************/ /* Main, everything is in while(1) loop. */ /****************************************************************************/ int main() { // pin state init H(DDRB, PB0); H(PORTB, PB0); H(DDRB, PB1); H(PORTB, PB1); L(DDRB, PB2); // PWM init H(TCCR0A, COM0A0); H(TCCR0A, COM0A1); H(TCCR0A, WGM00); H(TCCR0A, WGM01); H(TCCR0B, CS00); TCNT0 = 0x00; OCR0A = 0x00; // ADC init L(ADMUX, REFS0); H(ADMUX, REFS1); H(ADMUX, REFS2); H(ADMUX, ADLAR); L(ADCSRA, ADPS0); H(ADCSRA, ADPS1); H(ADCSRA, ADPS2); H(ADCSRA, ADEN); // INT0 init L(MCUCR, ISC00); L(MCUCR, ISC01); H(GIMSK, INT0); // enable interrupts (INT0) sei(); turn_off(); // main locals uint8_t adc = 0; uint8_t cnt = 0; while(1) { if(disable_sleep) continue; // get value from ADC differential mode 20x gain H(ADMUX, MUX0); H(ADMUX, MUX1); H(ADMUX, MUX2); H(ADCSRA, ADSC); while (ADCSRA & (1 << ADSC)); adc = ADCH; if (adc > ADC_LEVEL) { // turn on immediately when // there is someting on ADC input cnt = 0; turn_on(); } else { // count down to shut down mode cnt++; delay_ms(25); } if(cnt > 200) { // shut down after no sound cnt = 0; turn_off(); } // led pwm dimmer if(dimmer) { if(up) OCR0A++; else OCR0A--; if(OCR0A >= DIMMER_LEVEL) { up = 0; } if(OCR0A < 1) { up = 1; } delay_ms(10); } } }
Makefile
CPU=attiny45 GCC=avr-gcc CFLAGS= -Os -mmcu=$(CPU) -Wall -fpack-struct -fshort-enums -funsigned-bitfields -Wl,--relax -fno-move-loop-invariants -funsigned-char -fno-inline-small-functions -fdata-sections -fno-tree-loop-optimize -lprintf_min INCLUDES= LIBS= OBJCPY=avr-objcopy OBJECTS=main.o delay.o PROJECT_NAME=auto_speakers HEX_FILE=$(PROJECT_NAME).hex HEX_FILE_DUMP=$(PROJECT_NAME)_dump.hex # this line shoud be replaced by your programmator PROG=avrdude PROG_FLAGS=-V -c usbasp -p $(CPU) all: cls $(PROJECT_NAME) obj size #upload $(PROJECT_NAME): $(OBJECTS) $(GCC) -o $(PROJECT_NAME) $(OBJECTS) $(CFLAGS) $(LIBS) $(INCLUDES) main.o: main.c main.h $(GCC) $(CFLAGS) $(INCLUDES) -c main.c delay.o: delay.c delay.h $(GCC) $(CFLAGS) $(INCLUDES) -c delay.c obj: $(OBJECTS) $(OBJCPY) -O ihex $(PROJECT_NAME) $(HEX_FILE) clean: rm -f $(PROJECT_NAME) $(OBJECTS) $(HEX_FILE) cls: clear size: du -b $(HEX_FILE) # this line shoud be replaced by your programmator upload: all $(HEX_FILE) $(PROG) $(PROG_FLAGS) -e -U flash:w:$(HEX_FILE) # this line shoud be replaced by your programmator download: $(PROG) $(PROG_FLAGS) -U flash:r:$(HEX_FILE_DUMP) # this line shoud be replaced by your programmator reset: $(PROG) $(PROG_FLAGS)
No comments:
Post a Comment