#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdio.h>
#define F_CPU 16000000UL
#define RS_pin PB5
#define E_pin PB4
#define C1 PD0
#define C2 PD1
#define C3 PD2
#define C4 PD3
#ifndef XPCU
#define XPCU 16000000UL
#endif
#define __DELAY_BACKWARD_COMPATIBLE__
char call_matricial();
const char KEY[4][3] = {{'1','2','3'}, {'4','5','6'}, {'7', '8', '9'}, {'*', '0', '#'}};
int pressed = 0;
const float step_size = 0.0048828125;
int buzzer_status = 0;
unsigned long int frequency = 50;
int duty = 10;
int prescaler = 1;
unsigned int high_delay=0, low_delay=0;
int stop_buzzer = 0;
int allow_write = 1;
int allow = 1;
int counter=0;
unsigned long int get_frequency(int frequency[], int digits){
unsigned long int result = 0;
int i=0;
for (i=0; i<digits; i++){
result += (frequency[i])*pow(10, digits-1-i);
}
return result;
}
void delay_us(int d)
{
_delay_us(d);
}
void delay_ms(int d)
{
_delay_ms(d);
}
void iniciar_LCD(){
_delay_ms(2);
Entrar_cmd(0x33); //$33 for 4-bit mode
_delay_us(100);
Entrar_cmd(0x32); //$32 for 4-bit mode
_delay_us(100);
Entrar_cmd(0x28); //function set
_delay_us(100);
Entrar_cmd(0x0C); //Display ON/OFF
_delay_us(100);
Entrar_cmd(0x06); //Entry mode set
_delay_us(100);
Entrar_cmd(0x01); //Clear display
}
void Entrar_cmd(unsigned char cmd){
PORTB &= ~(1<<RS_pin); //RS = 0
PORTB = (PORTB & 0xF0) | (cmd>>4); //nibble alto
PORTB |= (1<<E_pin); //E = 1
_delay_us(100);
PORTB &= ~(1<<E_pin); //E = 0
_delay_us(100);
PORTB = (PORTB & 0xF0) | (cmd & 0x0F); //nibble bajo
PORTB |= (1<<E_pin); //E = 1
_delay_us(100);
PORTB &= ~(1<<E_pin); //E = 0
_delay_us(100);
}
void Entrar_data(unsigned char data){
PORTB |= (1<<RS_pin); //RS = 1
PORTB = (PORTB & 0xF0) | (data>>4); //nibble alto
PORTB |= (1<<E_pin); //E = 1
_delay_us(100);
PORTB &= ~(1<<E_pin); //E = 0
_delay_us(100);
PORTB = (PORTB & 0xF0) | (data & 0x0F); //nibble bajo
PORTB |= (1<<E_pin); //E = 1
_delay_us(100);
PORTB &= ~(1<<E_pin); //E = 0
_delay_us(100);
}
void goto_xy(unsigned char X, unsigned char Y){
if (Y==0){
Entrar_cmd(0x80 + X);
}
if (Y==1){
Entrar_cmd(0xC0 + X);
}
}
void mostrar_str(char *str){
int i;
for(i=0;str[i]!=0;i++)
{
Entrar_data(str[i]);
}
}
ISR (TIMER1_OVF_vect){
if (stop_buzzer==0){
int n0=0,n1=0,n2=0,n3=0;
if (buzzer_status==0){
n0 = (high_delay)&0xF;
n1 = (high_delay>>4)&0xF;
n2 = (high_delay>>8)&0xF;
n3 = (high_delay>>12)&0xF;
}
else{
n0 = (low_delay)&0xF;
n1 = (low_delay>>4)&0xF;
n2 = (low_delay>>8)&0xF;
n3 = (low_delay>>12)&0xF;
}
PORTC ^= 0b00000010;
buzzer_status = !buzzer_status;
TCNT1H = n3*16+n2;
TCNT1L = n1*16+n0;
}
}
int main(void)
{
ADMUX = 0b01000000;
ADCSRA= 0x87;
DDRC = 0b00000010;
PORTC = 0x00;
high_delay = 65536-(1/(float)frequency)*((float)duty/100)*XPCU/prescaler;
low_delay = 65536-(1/(float)frequency)*(1-(float)duty/100)*XPCU/prescaler;
TCCR1A = 0x00;
TCCR1B = 0x01;
TIMSK1 = (1<<TOIE1);
sei ();
stop_buzzer = 1;
DDRB = 0xFF;
PORTD = 0b00001111;
DDRD = 0b01110000;
const char clean_string[] = " ";
char string[50] = "";
int input_ADC;
int freq[7];
int changed_result=0;
int last_result = 0;
int i=0;
int set=0;
int start=0;
frequency=0;
iniciar_LCD();
goto_xy(0,0);
mostrar_str("Freq: ");
goto_xy(7, 0);
sprintf(string, "%ld", frequency);
mostrar_str(string);
strcpy(string, " Hz");
mostrar_str(string);
goto_xy(0,1);
mostrar_str("Vol : ");
goto_xy(7,1);
sprintf(string, "%d", duty);
mostrar_str(string);
strcpy(string, "%");
mostrar_str(string);
while(1){
allow_write = 1;
if ((allow_write && stop_buzzer==1) ||start==1){
ADCSRA|=(1<<ADSC);
while((ADCSRA&(1<<ADIF))==0);
input_ADC = ADC & 1023;
duty = (((float)input_ADC/1023))*100;
allow = 1;
if (last_result!=duty && allow==1){
last_result = duty;
changed_result = 1;
allow = 0;
}
start = 0;
}
char key = call_matricial();
if (key!=' ' && pressed==0){
if (set==0 && key!='*' && key!='#'){
set = 1;
i = 0;
goto_xy(7+i, 0);
mostrar_str(clean_string);
goto_xy(7+i, 0);
sprintf(string, "%c Hz", key);
mostrar_str(string);
freq[i] = key-'0';
i+= 1;
pressed = 1;
}
else{
if (key!='*' && key!='#' && i!=7){
if (i==0){
goto_xy(7, 0);
mostrar_str(clean_string);
goto_xy(7, 0);
}
goto_xy(7+i, 0);
sprintf(string, "%c Hz", key);
mostrar_str(string);
freq[i] = key-'0';
i += 1;
}
else if (key=='*'){
stop_buzzer = 1;
PORTC &= 0x00; // Off
set = 0;
}
else if (key=='#'){
frequency = get_frequency(freq, i);
high_delay = 65536-(1/(float)frequency)*((float)duty/100)*XPCU/prescaler;
low_delay = 65536-(1/(float)frequency)*(1-(float)duty/100)*XPCU/prescaler;
start = 1;
stop_buzzer = 0;
goto_xy(7, 0);
mostrar_str(clean_string);
goto_xy(7, 0);
if(frequency > 99){
sprintf(string, "%ld Hz", frequency+1);
mostrar_str(string);
set = 0;}
else{
sprintf(string, "%ld Hz", frequency);
mostrar_str(string);
set = 0;}
}
pressed = 1;
}
}
if (changed_result){
high_delay = 65536-(1/(float)frequency)*((float)duty/100)*XPCU/prescaler;
low_delay = 65536-(1/(float)frequency)*(1-(float)duty/100)*XPCU/prescaler;
goto_xy(7,1);
mostrar_str(clean_string);
goto_xy(7,1);
sprintf(string, "%d", duty);
mostrar_str(string);
strcpy(string, "%");
mostrar_str(string);
changed_result = 0;
}
}
return 0;
}
char call_matricial(){
int column;
for (column=0; column<3; column++){
PORTD = (~(1 << (column+4)))|(0b00001111);
if (!(PIND&0x01)){
return KEY[0][column];
}
else if (!(PIND&0x02)){
return KEY[1][column];
}
else if (!(PIND&0x04)){
return KEY[2][column];
}
else if (!(PIND&0x08)){
return KEY[3][column];
}
}
delay_ms(13);
pressed = 0;
return ' ';
}