nuclear@0: #define F_CLK 1000000 nuclear@0: #define F_CPU 1000000 nuclear@0: nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: nuclear@0: /* hardware setup nuclear@0: * - PORT D: data bits nuclear@0: * - PORT C nuclear@0: * bit 0: RS nuclear@0: * bit 1: R/W nuclear@0: * bit 2: E nuclear@0: */ nuclear@0: nuclear@0: #define BIT_RS 3 nuclear@0: #define BIT_RW 4 nuclear@0: #define BIT_E 5 nuclear@0: nuclear@0: #define CMD_CLEAR 1 nuclear@0: #define CMD_RET (1 << 1) nuclear@0: #define CMD_ENTRY_MODE (1 << 2) nuclear@0: #define CMD_ONOFF (1 << 3) nuclear@0: #define CMD_SHIFT (1 << 4) nuclear@0: #define CMD_FUNC (1 << 5) nuclear@0: #define CMD_CGRAM_ADDR (1 << 6) nuclear@0: #define CMD_DDRAM_ADDR (1 << 7) nuclear@0: nuclear@0: #define FUNC_BUS_4BIT 0 nuclear@0: #define FUNC_BUS_8BIT (1 << 4) nuclear@0: #define FUNC_LINES_1 0 nuclear@0: #define FUNC_LINES_2 (1 << 3) nuclear@0: #define FUNC_FONT_5x8 0 nuclear@0: #define FUNC_FONT_5x11 (1 << 2) nuclear@0: nuclear@0: #define ONOFF_DISP (1 << 2) nuclear@0: #define ONOFF_CURSOR (1 << 1) nuclear@0: #define ONOFF_CURSOR_POS 1 nuclear@0: nuclear@0: void setup_adc(void); nuclear@0: long read_adc(void); nuclear@0: nuclear@0: void lcd_init(void); nuclear@0: void lcd_clear(void); nuclear@0: void lcd_set_cursor_addr(unsigned int addr); nuclear@0: void lcd_putchar(char c); nuclear@0: void lcd_putstr(const char *str); nuclear@0: int lcd_stream_write(char c, FILE *fp); nuclear@0: void lcd_wait_busy(void); nuclear@0: static void enable(void); nuclear@0: static void set_bit(int bit); nuclear@0: static void clear_bit(int bit); nuclear@0: void delay(int x); nuclear@0: nuclear@0: #define NSDELAY() asm volatile ("nop") nuclear@0: #define DEBUG(i) (PORTB = (1 << (i))) nuclear@0: nuclear@0: FILE stream_lcd = FDEV_SETUP_STREAM(lcd_stream_write, NULL, _FDEV_SETUP_WRITE); nuclear@0: nuclear@0: int main(void) nuclear@0: { nuclear@0: stdout = stderr = &stream_lcd; nuclear@0: nuclear@0: DDRC = 0xfe; nuclear@0: PORTC = 0; /* disable pullups */ nuclear@0: nuclear@0: lcd_init(); nuclear@0: lcd_clear(); nuclear@0: nuclear@0: printf("initializing..."); nuclear@0: setup_adc(); nuclear@0: nuclear@0: for(;;) { nuclear@0: long val = read_adc(); nuclear@0: double ref = 1.08 * 1.47 / 0.47; nuclear@0: double voltage = ref * (double)val / (double)1024; nuclear@0: lcd_clear(); nuclear@0: nuclear@0: if(val == 1023) { nuclear@0: printf("*** RANGE *** "); nuclear@0: } else { nuclear@0: printf("%.2f volts ", voltage); nuclear@0: } nuclear@0: _delay_ms(500); nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void setup_adc(void) nuclear@0: { nuclear@0: /* disable digital input buffer on ADC0 pin */ nuclear@0: DIDR0 = 1; nuclear@0: nuclear@0: /* use the internal bandgap as a reference */ nuclear@0: ADMUX = 3 << REFS0; nuclear@0: nuclear@0: /* - enable ADC nuclear@0: * - set ADC clock prescaler to clock / 8 nuclear@0: */ nuclear@0: ADCSRA = (1 << ADEN) | (3 << ADPS0); nuclear@0: } nuclear@0: nuclear@0: long read_adc(void) nuclear@0: { nuclear@0: long low; nuclear@0: nuclear@0: /* start conversion */ nuclear@0: ADCSRA |= (1 << ADSC); nuclear@0: nuclear@0: /* wait while converting */ nuclear@0: while(ADCSRA & (1 << ADSC)); nuclear@0: nuclear@0: low = ADCL; nuclear@0: return low | ((long)ADCH << 8); nuclear@0: } nuclear@0: nuclear@0: void lcd_init(void) nuclear@0: { nuclear@0: DDRD = 0x0f; /* port d[0, 3] -> output */ nuclear@0: nuclear@0: /* make sure the display has time to boot up */ nuclear@0: _delay_ms(20); nuclear@0: nuclear@0: clear_bit(BIT_RW); nuclear@0: nuclear@0: clear_bit(BIT_E); nuclear@0: clear_bit(BIT_RS); nuclear@0: PORTD = CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8; nuclear@0: enable(); nuclear@0: lcd_wait_busy(); nuclear@0: nuclear@0: clear_bit(BIT_RS); nuclear@0: PORTD = CMD_ONOFF | ONOFF_DISP | ONOFF_CURSOR; nuclear@0: enable(); nuclear@0: lcd_wait_busy(); nuclear@0: nuclear@0: clear_bit(BIT_RS); nuclear@0: PORTD = CMD_ENTRY_MODE | (1 << 1); nuclear@0: enable(); nuclear@0: lcd_wait_busy(); nuclear@0: } nuclear@0: nuclear@0: void lcd_clear(void) nuclear@0: { nuclear@0: DDRD = 0xff; /* port d -> output */ nuclear@0: nuclear@0: clear_bit(BIT_RW); nuclear@0: nuclear@0: clear_bit(BIT_E); nuclear@0: clear_bit(BIT_RS); nuclear@0: PORTD = CMD_CLEAR; nuclear@0: enable(); nuclear@0: lcd_wait_busy(); nuclear@0: } nuclear@0: nuclear@0: void lcd_set_cursor_addr(unsigned int addr) nuclear@0: { nuclear@0: DDRD = 0xff; /* port d -> output */ nuclear@0: nuclear@0: clear_bit(BIT_RW); nuclear@0: nuclear@0: clear_bit(BIT_E); nuclear@0: clear_bit(BIT_RS); nuclear@0: PORTD = CMD_DDRAM_ADDR | addr; nuclear@0: enable(); nuclear@0: lcd_wait_busy(); nuclear@0: } nuclear@0: nuclear@0: void lcd_putchar(char c) nuclear@0: { nuclear@0: DDRD = 0xff; /* port d -> output */ nuclear@0: nuclear@0: clear_bit(BIT_RW); nuclear@0: nuclear@0: set_bit(BIT_RS); nuclear@0: PORTD = c; nuclear@0: enable(); nuclear@0: lcd_wait_busy(); nuclear@0: } nuclear@0: nuclear@0: void lcd_putstr(const char *str) nuclear@0: { nuclear@0: while(*str) { nuclear@0: lcd_putchar(*str++); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: int lcd_stream_write(char c, FILE *fp) nuclear@0: { nuclear@0: /* TODO terminal shit handling */ nuclear@0: lcd_putchar(c); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void lcd_wait_busy(void) nuclear@0: { nuclear@0: unsigned char data; nuclear@0: nuclear@0: DDRD = 0; /* port d -> input */ nuclear@0: PORTD = 0; /* disable pull-ups */ nuclear@0: nuclear@0: do { nuclear@0: NSDELAY(); nuclear@0: clear_bit(BIT_E); nuclear@0: clear_bit(BIT_RS); nuclear@0: set_bit(BIT_RW); nuclear@0: /*PIND = 0xff;*/ nuclear@0: nuclear@0: NSDELAY(); nuclear@0: set_bit(BIT_E); nuclear@0: NSDELAY(); nuclear@0: data = PIND; nuclear@0: clear_bit(BIT_E); nuclear@0: clear_bit(BIT_RW); nuclear@0: nuclear@0: } while(data & (1 << 7)); nuclear@0: nuclear@0: DDRD = 0xff; /* port d -> output */ nuclear@0: } nuclear@0: nuclear@0: static void enable(void) nuclear@0: { nuclear@0: NSDELAY(); nuclear@0: set_bit(BIT_E); nuclear@0: NSDELAY(); nuclear@0: clear_bit(BIT_E); nuclear@0: NSDELAY(); nuclear@0: } nuclear@0: nuclear@0: static void set_bit(int bit) nuclear@0: { nuclear@0: PORTC |= 1 << bit; nuclear@0: } nuclear@0: nuclear@0: static void clear_bit(int bit) nuclear@0: { nuclear@0: PORTC &= ~(1 << bit); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void delay(int x) nuclear@0: { nuclear@0: int i, j; nuclear@0: nuclear@0: while(x-- > 0) { nuclear@0: for(i=0; i<90; i++) { nuclear@0: for(j=0; j<6; j++) { nuclear@0: asm volatile("nop"); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: }