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