#include <stdio.h>
#include <util/delay.h>
//#define BUTTON_PIN_INTERRUPT PD2;
#define DATA0 PD0
#define DATA1 PD1
#define DATA2 PD2
#define DATA3 PD3
#define DATA4 PD4
#define DATA5 PD5
#define DATA6 PD6
#define DATA7 PD7
#define RS PB0
#define RW PB1
#define E PB2
// PIN ORDER RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
// CLEAR DISPLAY 00 0000 0001
// RETURN HOME 00 0000 0001
// ENTRY MODE SET 00 0000 01xx
// DISPLAY ON/OFF CONTROL 00 0001 1xxx
// CURSOR OR DISPLAY SHIFT 00 0001 xx--
// FUNCTION SET 00 1xxx xx--
// SET DDRAM ADDRESS 00 1
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}
};
const int DATAPINS[4] = {DATA4, DATA5, DATA6, DATA7};
int main(void)
{
//INIT_ADC();
INIT_DATAPINS();
INIT_LCD();
PORTD = 0;
LCD_DISPLAY_STRING("Voltage:", 8);
LCD_DISPLAY_STRING("V", 1);
LCD_SET_CURSOR_POSITION(1,0);
LCD_DISPLAY_STRING("Light:", 6);
LCD_SET_CURSOR_POSITION(1,15);
LCD_DISPLAY_STRING("%", 1);
while (1);
}
void SET_DATA_PINS(uint8_t){
//uint8_t
}
void INIT_LCD(void){
PORTB &= (0 << RS);
LCD_FUNCTION_SET();
LCD_DISPLAY_ON_OFF_CONTROL();
//LCD_ENTRY_MODE_SET();
PORTB |= (1 << RS);
}
void LCD_DISPLAY_STRING(char* str, uint8_t length){
for(int i = 0; i < length; i++){
char character = str[i];
LCD_DISPLAY_CHAR(character);
}
}
void LCD_DISPLAY_CHAR(unsigned int ascii_value){
// 1010 0011
// Shifting the number 4 times right, separates the higher bits (value >> 4)
PORTD = ascii_value;
LCD_ENABLE();
}
/*TELLS LCD TO USE 4 DATA-PINS FOR INFORMATION. ENABLES DISPLAY TO USE 2 LINES OF TEXT.
FUNCTION SET
RS: 0
RW: 0
MODE: ->4-bit DATA4 LOW
8-bit DATA4 HIGH
LINENUMBER: 1-line DATA3 LOW
-> 2-line DATA3 HIGH
DOTS: -> 5x8 DOTS LETTERS DATA2 LOW
5x11 DOTS LETTERS DATA2 HIGH */
void LCD_FUNCTION_SET(void){
// 0011 1000 4-bit mode
//LCD_CLEAR_DATA_BITS;
PORTD = (0 << DATA7) | (0 << DATA6) | (1 << DATA5) | (1 << DATA4) | (1 << DATA3);
LCD_ENABLE();
// 0011 1000 4-bit mode, 2 lines
//LCD_CLEAR_DATA_BITS;
PORTD = (0 << DATA7) | (0 << DATA6) | (1 << DATA5) | (1 << DATA4);
LCD_ENABLE();
PORTD = (1 << DATA7) | (0 << DATA6) | (0 << DATA5) | (0 << DATA4);
LCD_ENABLE();
}
void INIT_DATAPINS(void){
#define RS PB0
#define RW PB1
#define E PB2
DDRB = (1 << E) | (1 << RS) | (1 << RW);
DDRD = (1 << DATA7) | (1 << DATA6) | (1 << DATA5) | (1 << DATA4) | (1 << DATA3) | (1 << DATA2)| (1 << DATA1) | (1 << DATA0);
}
/* CLEARS ENTIRE DISPLAY, AND SENDS CURSOR TO STARTING POSITION
CLEAR DISPLAY
RS: 0
RW: 0 */
void LCD_CLEAR_DISPLAY(void){
// 0000 0001 CLEAR DISPLAY
PORTD = 0;
//PORTD |= (0 << DATA7) | (0 << DATA6) | (0 << DATA5) | (0 << DATA4) | (0 << DATA3) | (0 << DATA2) | (0 << DATA1) | (1 << DATA0);
LCD_ENABLE();
}
/* SENDS CURSOR TO STARTING POSITION
CLEAR DISPLAY
RS: 0
RW: 0 */
void LCD_RETURN_HOME(void){
// 0000 0010 RETURN HOME
PORTD = 0;
//PORTD |= (0 << DATA7) | (0 << DATA6) | (0 << DATA5) | (0 << DATA4) | (0 << DATA3) | (0 << DATA2) | (1 << DATA1) | (0 << DATA0);
LCD_ENABLE();
}
/* TELLS THE LCD TO READ DATAPINS, RW & RS PINS, AND DO OPERATION. THE ENABLE-PIN IS HIGH FOR A SHORT WHILE, THEN GOES LOW AGAIN.
AFTER SETTING UP THE DATAPINS, THE ENABLE NEEDS TO BE TOGGLED FOR THE CHARACTER TO DISPLAY.
E: 1 */
void LCD_ENABLE(void){
_delay_us(1);
PORTB ^= (1 << E);
_delay_us(1);
PORTB ^= (1 << E);
_delay_us(1);
}
void LCD_SET_CURSOR_POSITION(int row, int column){
LCD_SET_DDRAM_ADDRESS(CURSOR_POSITIONS[row][column]);
//Serial.println(CURSOR_POSITIONS[row][column]);
}
void LCD_SET_DDRAM_ADDRESS(unsigned char address){
PORTB &= (0 << RS);
PORTD = 128;
PORTD |= address;
LCD_ENABLE();
PORTB |= (1 << RS);
}
/*SETTINGS FOR DISPLAY ON/OFF, CURSOR ON/OFF, BLINKING CURSOR ON/OFF
FUNCTION SET
RS: 0
RW: 0
DISPLAY ON/OFF: DISPLAY OFF DATA2 LOW
->DISPLAY ON DATA2 HIGH
CURSOR ON/OFF: CURSOR OFF DATA1 LOW
-> CURSOR ON DATA1 HIGH
BLINKING ON/OFF: -> BLINKING CURSOR OFF DATA0 LOW
BLINKING CURSOR ON DATA0 HIGH */
void LCD_DISPLAY_ON_OFF_CONTROL(void){
// 0000 1111 DISPLAY ON, CURSOR ON, BLINK ON
//LCD_CLEAR_DATA_BITS;
PORTD = 0;
PORTD |= (0 << DATA7) | (0 << DATA6) | (0 << DATA5) | (0 << DATA4) | (1 << DATA3) | (1 << DATA2) | (1 << DATA1) | (1 << DATA0);
LCD_ENABLE();
}
/*SETTINGS FOR WHICH WAY THE CURSOR MOVES, CONTROLS TO SHIFT ENTIRE DISPLAY LEFT/RIGHT
FUNCTION SET
RS: 0
RW: 0
INCREMENT/DECREMENT: CURSOR TO LEFT DATA1 LOW
->CURSOR TO RIGHT DATA1 HIGH
IF INCREMENT IS HIGH = SHIFT LEFT, INCREMENT IS LOW = SHIFT RIGHT
SHIFT LEFT/RIGHT: SHIFT DATA0 HIGH
BLINKING ON/OFF: BLINKING CURSOR OFF DATA0 LOW
->BLINKING CURSOR ON DATA0 HIGH */
void LCD_ENTRY_MODE_SET(void){
// 0000 0000 Left->Right
PORTD = 0;
PORTD |= (0 << DATA7) | (1 << DATA6) | (1 << DATA5) | (0 << DATA4) | (0 << DATA3) | (0 << DATA2) | (0 << DATA1) | (0 << DATA0);
LCD_ENABLE();
}
ISR(ADC_vect){
float percent = ((float)ADC/1024)*100;
Serial.print("ADC: ");
//Serial.print(percent, 2);
Serial.println(ADC);
//Serial.println("%");
ADCSRA |= (1 << ADSC);
}
void INIT_ADC(void){
ADMUX |= (1 << REFS0); //INTERNAL REF
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE)| (0 << ADLAR); // ADC ENABLE, START CONVERSION, ENABLE INTERRUPTS
ADCSRB = (0 << ADTS2) | (0 << ADTS1)| (0 << ADTS0); // FREE-RUNNING MODE
DIDR0 = (1 << ADC0D); // DISABLE DIGITAL INPUT BUFFER
sei();
}