#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdio.h>
#define F_CPU 16000000UL
#define C1 PB0
#define C2 PB1
#define C3 PB2
#define C4 PB3
#define LCD_Port PORTD //Define LCD Port (PORTA, PORTB, PORTC, PORTD)
#define LCD_DPin DDRD //Define 4-Bit Pins (PD4-PD7 at PORT D)
#define RSPIN PD2 //RS Pin
#define ENPIN PD3 //E Pin
#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;
void LCD_Action( unsigned char cmnd );
void LCD_Init (void);
void LCD_Clear();
void LCD_Print (const char *str);
void LCD_Printpos (char row, char pos, char *str);
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 LCD_Init (void)
{
LCD_DPin = 0xFF; //Control LCD Pins (D4-D7)
_delay_ms(15); //Wait before LCD activation
LCD_Action(0x02); //4-Bit Control
LCD_Action(0x28); //Control Matrix @ 4-Bit
LCD_Action(0x0c); //Disable Cursor
LCD_Action(0x06); //Move Cursor
LCD_Action(0x01); //Clean LCD
_delay_ms(2);
}
void LCD_Action( unsigned char cmnd )
{
LCD_Port = (LCD_Port & 0x0F) | (cmnd & 0xF0);
LCD_Port &= ~ (1<<RSPIN);
LCD_Port |= (1<<ENPIN);
_delay_us(1);
LCD_Port &= ~ (1<<ENPIN);
_delay_us(200);
LCD_Port = (LCD_Port & 0x0F) | (cmnd << 4);
LCD_Port |= (1<<ENPIN);
_delay_us(1);
LCD_Port &= ~ (1<<ENPIN);
_delay_ms(2);
}
void LCD_Clear()
{
LCD_Action (0x01); //Clear LCD
_delay_ms(2); //Wait to clean LCD
LCD_Action (0x80); //Move to Position Line 1, Position 1
}
void LCD_Print (const char *str)
{
int i;
for(i=0; str[i]!=0; i++)
{
LCD_Port = (LCD_Port & 0x0F) | (str[i] & 0xF0);
LCD_Port |= (1<<RSPIN);
LCD_Port|= (1<<ENPIN);
_delay_us(1);
LCD_Port &= ~ (1<<ENPIN);
_delay_us(200);
LCD_Port = (LCD_Port & 0x0F) | (str[i] << 4);
LCD_Port |= (1<<ENPIN);
_delay_us(1);
LCD_Port &= ~ (1<<ENPIN);
_delay_ms(2);
}
}
//Write on a specific location
void LCD_Printpos (char row, char pos)
{
if (row == 0 && pos<16)
LCD_Action((pos & 0x0F)|0x80);
else if (row == 1 && pos<16)
LCD_Action((pos & 0x0F)|0xC0);
//LCD_Print(str);
}
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;
LCD_Init();
LCD_Printpos(0,0);
LCD_Print("Freq: ");
LCD_Printpos(0, 7);
sprintf(string, "%ld", frequency);
LCD_Print(string);
strcpy(string, " Hz");
LCD_Print(string);
LCD_Printpos(1,0);
LCD_Print("Vol : ");
LCD_Printpos(1,7);
sprintf(string, "%d", duty);
LCD_Print(string);
strcpy(string, "%");
LCD_Print(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;
LCD_Printpos(0, 7+i);
LCD_Print(clean_string);
LCD_Printpos(0, 7+i);
sprintf(string, "%c Hz", key);
LCD_Print(string);
freq[i] = key-'0';
i+= 1;
pressed = 1;
}
else{
if (key!='*' && key!='#' && i!=7){
if (i==0){
LCD_Printpos(0, 7);
LCD_Print(clean_string);
LCD_Printpos(0, 7);
}
LCD_Printpos(0, 7+i);
sprintf(string, "%c Hz", key);
LCD_Print(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;
LCD_Printpos(0, 7);
LCD_Print(clean_string);
LCD_Printpos(0, 7);
if(frequency > 99){
sprintf(string, "%ld Hz", frequency+1);
LCD_Print(string);
set = 0;}
else{
sprintf(string, "%ld Hz", frequency);
LCD_Print(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;
LCD_Printpos(1,7);
LCD_Print(clean_string);
LCD_Printpos(1,7);
sprintf(string, "%d", duty);
LCD_Print(string);
strcpy(string, "%");
LCD_Print(string);
changed_result = 0;
}
}
return 0;
}
char call_matricial(){
int column;
for (column=0; column<3; column++){
//PORTD = (~(1 << (column+4)))|(0b00001111);
PORTC |= (1<<column);
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 ' ';
}
/*
char leer_keypad() {
//int column;
//for (column=0; column<3; column++){
PORTC |= (1<<0);
//PORTC = 0xF8; //R1
if (!(PIND & (1 << C1))){
return KEY[0][0];
}
if (!(PIND & (1 << C2))){
return KEY[0][1];
}
if (!(PIND & (1 << C3))){
return KEY[0][2];
}
if (!(PIND & (1 << C4))){}
PORTC |= (1<<1);
//PORTC = 0xF4; //R2
if (!(PIND & (1 << C1))){
return KEY[1][0];
}
if (!(PIND & (1 << C2))){
return KEY[1][1];
}
if (!(PIND & (1 << C3))){
return KEY[1][2];
}
if (!(PIND & (1 << C4))){}
PORTC |= (1<<2);
//PORTC = 0xEC; //R3
if (!(PIND & (1 << C1))){
return KEY[2][0];
}
if (!(PIND & (1 << C2))){
return KEY[2][1];
}
if (!(PIND & (1 << C3))){
return KEY[2][2];
}
if (!(PIND & (1 << C4))){}
PORTC |= (1<<3);
//PORTC = 0xDF; //R4
if (!(PIND & (1 << C1))){
return KEY[3][0];
}
if (!(PIND & (1 << C2))){
return KEY[3][1];
}
if (!(PIND & (1 << C3))){
return KEY[3][2];
}
if (!(PIND & (1 << C4))){}
//}
_delay_ms(10);
pressed = 0;
return ' ';
}*/