/*******************************************************
This program was created by the
CodeWizardAVR V3.10 Evaluation
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Chip type : ATtiny13
AVR Core Clock frequency: 1,200000 MHz
Memory model : Tiny
External RAM size : 0
Data Stack size : 16
*******************************************************/
#include <tiny13.h>
#include <delay.h>
#define PIN_KEY_S1 PINB.0
#define PULLUP_KEY_S1 PORTB.0
#define PIN_SOUND_L PINB.2
#define PULLUP_SOUND_L PORTB.2
#define P_LED1_GREEN PORTB.1
#define DP_LED1_GREEN DDRB.1
#define LED1_GREEN_ON P_LED1_GREEN = 1;
#define LED1_GREEN_OFF P_LED1_GREEN = 0;
#define P_LED2_RED PORTB.3
#define DP_LED2_RED DDRB.3
#define LED2_RED_ON P_LED2_RED = 1;
#define LED2_RED_OFF P_LED2_RED = 0;
#define DP_PWM DDRB.1
#define TIMER_START TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
#define TIMER_STOP TCCR0B=0;
#define TIMER_CLEAR TCNT0=0;
//#define DEBUGMODE
volatile unsigned char measuredTime;
volatile bit bTimerRunning = 0;
volatile bit bMeasuringComplete = 0;
volatile bit bErrorOverflow = 0;
eeprom unsigned char EE_osccal @ 0x3F; // OSCCAL will be written to EEPROM at address 0x3F
// Pin change interrupt service routine
interrupt [PC_INT0] void pin_change_isr(void)
{
if(bTimerRunning)
{
TIMER_STOP;
measuredTime = TCNT0;
bTimerRunning = 0;
TIMER_CLEAR;
bMeasuringComplete = 1;
}
else
{
TIMER_START;
bTimerRunning = 1;
}
if(TIFR0 & (1 << TOV0))
{
bErrorOverflow = 1;
GIMSK=(0<<INT0) | (0<<PCIE);
}
GIFR=(1<<PCIF);
}
void initTimer_MeasureAudioFrequency(void)
{ // audio frames come every 1ms
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 150,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 1,7067 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
//TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
TCCR0B=0; // disable timer
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
}
void initTimer_OutputFrequency(void)
{
DP_PWM = 1; // enable Timer output pin
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 150,000 kHz
// Mode: Fast PWM top=OCR0A
// OC0A output: Disconnected
// OC0B output: Non-Inverted PWM
// Timer Period: 1 ms
// Output Pulse(s):
// OC0B Period: 1 ms Width: 0,79866 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(1<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x95;
OCR0B=0x77;
}
void initExtInt(void)
{
// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: On
GIMSK=(0<<INT0) | (1<<PCIE);
MCUCR=(0<<ISC01) | (0<<ISC00);
PCMSK=(0<<PCINT5) | (0<<PCINT4) | (0<<PCINT3) | (1<<PCINT2) | (0<<PCINT1) | (0<<PCINT0);
GIFR=(0<<INTF0) | (1<<PCIF);
}
#ifdef DEBUGMODE
#define P_UART_TX P_LED2_RED
#define DP_UART_TX DP_LED2_RED
#define DEBUG_ARRAYSIZE 8
unsigned char debugTime[DEBUG_ARRAYSIZE];
void initUart(void)
{
P_UART_TX = 1;
DP_UART_TX = 1;
}
void sendUartChar(char c)
{
#define UART_DELAYTIME /*760*/ 800 // 1200 Bd
unsigned char i;
P_UART_TX = 0; // Startbit
delay_us(UART_DELAYTIME);
for(i = 0; i < 8; i++)
{
if(c & 0x01)
{
P_UART_TX = 1;
}
else
{
P_UART_TX = 0;
}
c >>= 1;
delay_us(UART_DELAYTIME);
}
P_UART_TX = 1; // Stopbit
delay_us(UART_DELAYTIME);
}
void sendUart(char *s)
{
while(*s)
{
sendUartChar(*s);
s++;
}
}
#endif //DEBUGMODE
void main(void)
{
#define OSCCAL_RANGE 0x20 // allowed range +- from factory loaded OSCCAL
unsigned char min, max, value, cnt;
#ifdef DEBUGMODE
unsigned char i = 0;
#endif
// Crystal Oscillator division factor: 8
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (1<<CLKPS1) | (1<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<ACME);
initTimer_MeasureAudioFrequency();
PIN_KEY_S1 = 1;
PULLUP_SOUND_L = 1;
LED1_GREEN_ON;
DP_LED1_GREEN = 1;
delay_ms(1000);
LED2_RED_ON;
DP_LED2_RED = 1;
initExtInt();
while(PIN_KEY_S1); // wait until key pressed
while(PIN_SOUND_L == 0); // wait until audio idle (High)
LED1_GREEN_OFF;
GIFR=(1<<PCIF); // clear EXTINT flag
#asm("sei")
if(OSCCAL >= OSCCAL_RANGE)
min = OSCCAL - OSCCAL_RANGE;
else
min = 0;
if(OSCCAL <= (0x7F - OSCCAL_RANGE))
max = OSCCAL + OSCCAL_RANGE;
else
max = 0x7F;
cnt = 4;
do
{
value = (max - min) / 2 + min;
OSCCAL = value;
while(!bMeasuringComplete && !bErrorOverflow); // wait until Audio measuring complete ...
if(bErrorOverflow)
{
break;
}
cnt++;
if(cnt == 5)
{ // ignore measurement of startbits because of too high tolerances
cnt = 0;
continue;
}
#ifdef DEBUGMODE
if(i < DEBUG_ARRAYSIZE)
{
debugTime[i] = measuredTime;
i++;
}
#endif
if(measuredTime == 150)
{
break;
}
else if(measuredTime < 150)
{
min = value;
}
else
{
max = value;
}
bMeasuringComplete = 0;
}
while((max - min) > 1);
GIMSK=(0<<PCIE); // disable ExtInt
#ifdef DEBUGMODE
initUart();
sendUart("Time:");
for(i = 0; i < DEBUG_ARRAYSIZE; i++)
{
sendUartChar(debugTime[i]);
}
sendUart("OSCCAL:");
sendUartChar(OSCCAL);
#endif
delay_ms(100);
if(bErrorOverflow)
{
LED2_RED_ON;
while(1)
{ // timer overflow => red LED ON, green blinking fast (4 Hz)
LED1_GREEN_ON;
delay_ms(125);
LED1_GREEN_OFF;
delay_ms(125);
}
}
if( (measuredTime > (150+7)) || (measuredTime < (150-7)) )
{
LED2_RED_ON;
while(1)
{ // too high tolerance => red LED ON, green blinking slow (2 Hz)
LED1_GREEN_ON;
delay_ms(250);
LED1_GREEN_OFF;
delay_ms(250);
}
}
EE_osccal = OSCCAL;
TIMER_STOP;
TIMER_CLEAR;
initTimer_OutputFrequency();
LED2_RED_OFF; // success => red LED off
P_LED1_GREEN = 0;
while (1)
{ // blink green LED with 1Hz, modulated with 1 kHz @ 80% duty cycle
delay_ms(500);
DP_PWM = 0;
delay_ms(500);
DP_PWM = 1;
}
}