#define F_CPU 16000000
#include <avr/delay.h>
#include <stdbool.h>
#define DATA0 PD0
#define DATA1 PD1
#define DATA2 PD2
#define DATA3 PD4
#define DATA4 PD5
#define DATA5 PD6
#define DATA6 PD7
#define DATA7 PB0
#define RS PB1
#define RW PB2
#define E PB3
int pins_data[8] = {DATA0, DATA1, DATA2, DATA3, DATA4, DATA5, DATA6, DATA7};
int pins_misc[3] = {RS, RW, E};
const uint8_t CURSOR_POSITIONS[2][16] = {
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F},
{0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F}
};
unsigned int bit_mask[8] = {0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000, 0b01000000, 0b10000000};
bool bits[8];
int main(void){
SET_DDR(pins_data, pins_misc);
LCD_SETUP();
ADC_INIT();
//TIMER1_INIT();
LCD_CURSOR_POSITION(1, 4);
LCD_DISPLAY_STRING("HELLO", 5);
LCD_CURSOR_POSITION(2, 3);
LCD_DISPLAY_STRING("friend", 6);
//LCD_CLEAR_DISPLAY();
}
void LCD_CLEAR_DISPLAY(void){
PORTB &= ~(1 << RS);
LCD_SET_DATA_PINS(1);
LCD_ENABLE();
PORTB |= (1 << RS);
}
void LCD_CURSOR_POSITION(uint8_t row, uint8_t column){
PORTB &= ~(1 << RS);
LCD_SET_ADDRESS(CURSOR_POSITIONS[row - 1][column - 1]);
LCD_ENABLE();
PORTB |= (1 << RS);
}
void LCD_SET_ADDRESS(uint8_t address){
LCD_SET_DATA_PINS(address);
PORTB |= (1 << DATA7);
LCD_ENABLE();
}
void LCD_DISPLAY_STRING(char* str, int size){
for(int i = 0; i < size; i++){
LCD_DISPLAY_CHAR(str[i]);
}
}
void LCD_DISPLAY_CHAR(char ascii_code){
LCD_SET_DATA_PINS(ascii_code);
LCD_ENABLE();
}
void LCD_SETUP(){
LCD_CLEAR_DATA_PINS(pins_data);
PORTB &= ~(1 << RS); // 0 for CONFIGURATION MODE
PORTB &= ~(1 << RW); // 0 for WRITE
// ENTRY MODE SET
// CURSOR DIRECTION RIGHT
LCD_SET_DATA_PINS(0b00000110);
LCD_ENABLE();
// DISPLAY ON/OFF CONTROL
// DISPLAY ON, CURSOR ON
LCD_SET_DATA_PINS(0b0001110);
LCD_ENABLE();
// FUNCTION SET
// 8-BIT MODE, 2 LINES
LCD_SET_DATA_PINS(0b00111000);
LCD_ENABLE();
PORTB |= (1 << RS); // 1 for WRITE MODE
LCD_CLEAR_DATA_PINS(pins_data);
}
void LCD_CLEAR_DATA_PINS(int* pins){
for(int i = 0; i < 8; i++){
if(i < 7){
PORTD &= (0 << pins[i]);
}else {
PORTB &= ~(1 << pins[7]);
}
}
}
void LCD_SET_DATA_PINS(uint8_t value){
decToBin(bit_mask, bits, value);
for(int j = 0; j < 8; j++){
if(bits[j] && j < 7){
PORTD |= (1 << pins_data[j]);
}else if(bits[j]){
PORTB |= (1 << pins_data[j]);
}
}
}
/*Arguments: array of masks for the 8 individual bits,
bool array to store the binary numbers in,
8bit unsigned decimal,
Return: Nothing. Stores result in the bit-array*/
void decToBin(unsigned int mask[], bool bits[], unsigned int value){
for(int i = 0; i<8; i++){
unsigned int bit_status = value & mask[i];
bits[i] = bit_status ? 1 : 0;
}
}
void SET_DDR(int* data_pins, int* misc_pins){
for(int i = 0; i < 8; i++){
if(i < 7){
DDRD |= (1 << data_pins[i]);
}else{
DDRB |= (1 << data_pins[i]);
}
}
//
for(int j = 0; j < 3; j++){
DDRB |= (1 << misc_pins[j]);
}
// D2 as INPUT
DDRD |= (1 << PD2);
}
void LCD_ENABLE(void){
_delay_us(1);
PORTB ^= (1 << E);
_delay_us(1);
PORTB ^= (1 << E);
_delay_us(1);
LCD_CLEAR_DATA_PINS(pins_data);
}
void ADC_INIT(){
ADMUX |= (1 << REFS0); //INTERNAL REF
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE)| (0 << ADLAR); // ADC ENABLE, START CONVERSION, ENABLE INTERRUPTS
ADCSRB = (1 << ADTS2) | (0 << ADTS1)| (1 << ADTS0); // TIMER1 COMPARE B
DIDR0 = (1 << ADC0D); // DISABLE DIGITAL INPUT BUFFER
sei();
}
void TIMER1_INIT(void){
TCCR1A = (1 << WGM11) | (1 << WGM10);
TCCR1B = (1 << WGM12) | (1 << CS12) | (0 << CS11) | (1 << CS10); // CTC Mode
//TCCR1C = ();
TIMSK1 = (1 << OCIE1B);
OCR1B = 20000;
}
ISR(ADC_vect){
LCD_DISPLAY_STRING("2", 3);
ADCSRA |= (1 << ADSC);
}