pwcdecode
annotate pwcdecode.c @ 0:050c04723d37
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 01 Nov 2013 09:40:20 +0200 |
parents | |
children | 4ea5d2920f89 |
rev | line source |
---|---|
nuclear@0 | 1 #define F_CLK 1000000 |
nuclear@0 | 2 #define F_CPU 1000000 |
nuclear@0 | 3 |
nuclear@0 | 4 #include <stdio.h> |
nuclear@0 | 5 #include <avr/io.h> |
nuclear@0 | 6 #include <avr/interrupt.h> |
nuclear@0 | 7 #include <util/delay.h> |
nuclear@0 | 8 |
nuclear@0 | 9 /* hardware setup |
nuclear@0 | 10 * - PORT D: data bits |
nuclear@0 | 11 * - PORT C |
nuclear@0 | 12 * bit 3: RS |
nuclear@0 | 13 * bit 4: R/W |
nuclear@0 | 14 * bit 5: E |
nuclear@0 | 15 */ |
nuclear@0 | 16 #define LCD_BUS_WIDTH 8 |
nuclear@0 | 17 |
nuclear@0 | 18 #define BIT_RS 3 |
nuclear@0 | 19 #define BIT_RW 4 |
nuclear@0 | 20 #define BIT_E 5 |
nuclear@0 | 21 |
nuclear@0 | 22 #define CMD_CLEAR 1 |
nuclear@0 | 23 #define CMD_RET (1 << 1) |
nuclear@0 | 24 #define CMD_ENTRY_MODE (1 << 2) |
nuclear@0 | 25 #define CMD_ONOFF (1 << 3) |
nuclear@0 | 26 #define CMD_SHIFT (1 << 4) |
nuclear@0 | 27 #define CMD_FUNC (1 << 5) |
nuclear@0 | 28 #define CMD_CGRAM_ADDR (1 << 6) |
nuclear@0 | 29 #define CMD_DDRAM_ADDR (1 << 7) |
nuclear@0 | 30 |
nuclear@0 | 31 #define FUNC_BUS_4BIT 0 |
nuclear@0 | 32 #define FUNC_BUS_8BIT (1 << 4) |
nuclear@0 | 33 #define FUNC_LINES_1 0 |
nuclear@0 | 34 #define FUNC_LINES_2 (1 << 3) |
nuclear@0 | 35 #define FUNC_FONT_5x8 0 |
nuclear@0 | 36 #define FUNC_FONT_5x11 (1 << 2) |
nuclear@0 | 37 |
nuclear@0 | 38 #define ONOFF_DISP (1 << 2) |
nuclear@0 | 39 #define ONOFF_CURSOR (1 << 1) |
nuclear@0 | 40 #define ONOFF_CURSOR_POS 1 |
nuclear@0 | 41 |
nuclear@0 | 42 void lcd_init(void); |
nuclear@0 | 43 void lcd_clear(void); |
nuclear@0 | 44 void lcd_set_cursor_addr(unsigned int addr); |
nuclear@0 | 45 void lcd_putchar(char c); |
nuclear@0 | 46 void lcd_putstr(const char *str); |
nuclear@0 | 47 int lcd_stream_write(char c, FILE *fp); |
nuclear@0 | 48 void lcd_wait_busy(void); |
nuclear@0 | 49 static void enable(void); |
nuclear@0 | 50 static void set_bit(int bit); |
nuclear@0 | 51 static void clear_bit(int bit); |
nuclear@0 | 52 void delay(int x); |
nuclear@0 | 53 |
nuclear@0 | 54 #define NSDELAY() asm volatile ("nop") |
nuclear@0 | 55 #define DEBUG(i) (PORTB = (1 << (i))) |
nuclear@0 | 56 |
nuclear@0 | 57 FILE stream_lcd = FDEV_SETUP_STREAM(lcd_stream_write, NULL, _FDEV_SETUP_WRITE); |
nuclear@0 | 58 |
nuclear@0 | 59 unsigned int pulse_time; |
nuclear@0 | 60 |
nuclear@0 | 61 int main(void) |
nuclear@0 | 62 { |
nuclear@0 | 63 stdout = stderr = &stream_lcd; |
nuclear@0 | 64 |
nuclear@0 | 65 DDRB = 0; /* set port B as input (bit 0 is used to measure pulse width) */ |
nuclear@0 | 66 PORTB = 0; /* disable pullups */ |
nuclear@0 | 67 |
nuclear@0 | 68 DDRD = 0xff; |
nuclear@0 | 69 DDRC = 0xfe; |
nuclear@0 | 70 PORTC = 0; /* disable pullups */ |
nuclear@0 | 71 |
nuclear@0 | 72 lcd_init(); |
nuclear@0 | 73 lcd_clear(); |
nuclear@0 | 74 |
nuclear@0 | 75 printf("initializing..."); |
nuclear@0 | 76 |
nuclear@0 | 77 TCCR1B |= (1 << ICES1); /* set first capture to occur on a rising edge */ |
nuclear@0 | 78 TCCR1B = (TCCR1B & 0xf8) | 1; /* no prescaling */ |
nuclear@0 | 79 TIMSK1 |= (1 << ICIE1); /* enable timer1 input capture interrupt */ |
nuclear@0 | 80 sei(); |
nuclear@0 | 81 |
nuclear@0 | 82 for(;;) { |
nuclear@0 | 83 static int blink = 0; |
nuclear@0 | 84 |
nuclear@0 | 85 PORTB = blink ? 1 : 0; |
nuclear@0 | 86 blink = (blink + 1) & 1; |
nuclear@0 | 87 |
nuclear@0 | 88 lcd_set_cursor_addr(0); |
nuclear@0 | 89 printf("pulse time: %u us ", pulse_time); |
nuclear@0 | 90 lcd_set_cursor_addr(64); |
nuclear@0 | 91 printf("pos: %u%% ", (pulse_time - 1000) / 10); |
nuclear@0 | 92 _delay_ms(100); |
nuclear@0 | 93 } |
nuclear@0 | 94 return 0; |
nuclear@0 | 95 } |
nuclear@0 | 96 |
nuclear@0 | 97 ISR(TIMER1_CAPT_vect) |
nuclear@0 | 98 { |
nuclear@0 | 99 static int rising; |
nuclear@0 | 100 |
nuclear@0 | 101 rising = !rising; |
nuclear@0 | 102 if(rising) { |
nuclear@0 | 103 /* rising edge: reset the timer */ |
nuclear@0 | 104 TCNT1 = 0; |
nuclear@0 | 105 /* and set a falling edge trigger */ |
nuclear@0 | 106 TCCR1B &= ~(1 << ICES1); |
nuclear@0 | 107 } else { |
nuclear@0 | 108 /* falling edge: calculate the time since the last rise */ |
nuclear@0 | 109 pulse_time = ICR1; |
nuclear@0 | 110 /* and set a rising edge trigger */ |
nuclear@0 | 111 TCCR1B |= 1 << ICES1; |
nuclear@0 | 112 } |
nuclear@0 | 113 } |
nuclear@0 | 114 |
nuclear@0 | 115 void lcd_write_byte(unsigned char byte) |
nuclear@0 | 116 { |
nuclear@0 | 117 #if LCD_BUS_WIDTH == 8 |
nuclear@0 | 118 DDRD = 0xff; |
nuclear@0 | 119 PORTD = byte; |
nuclear@0 | 120 #else |
nuclear@0 | 121 DDRD = (DDRD & 0xf0) | 0xf; |
nuclear@0 | 122 |
nuclear@0 | 123 PORTD = (PORTD & 0xf0) | ((byte >> 4) & 0xf); |
nuclear@0 | 124 PORTD = (PORTD & 0xf0) | (byte & 0xf); |
nuclear@0 | 125 #endif |
nuclear@0 | 126 } |
nuclear@0 | 127 |
nuclear@0 | 128 unsigned char lcd_read_byte(void) |
nuclear@0 | 129 { |
nuclear@0 | 130 #if LCD_BUS_WIDTH == 8 |
nuclear@0 | 131 DDRD = 0; |
nuclear@0 | 132 PORTD = 0; /* disable pull-ups */ |
nuclear@0 | 133 |
nuclear@0 | 134 return PIND; |
nuclear@0 | 135 #else |
nuclear@0 | 136 unsigned char byte; |
nuclear@0 | 137 |
nuclear@0 | 138 DDRD = DDRD & 0xf0; |
nuclear@0 | 139 PORTD &= 0xf0; /* disable pull-ups */ |
nuclear@0 | 140 |
nuclear@0 | 141 byte = (PIND & 0xf) << 4; |
nuclear@0 | 142 return byte | (PIND & 0xf); |
nuclear@0 | 143 #endif |
nuclear@0 | 144 } |
nuclear@0 | 145 |
nuclear@0 | 146 void lcd_init(void) |
nuclear@0 | 147 { |
nuclear@0 | 148 /* make sure the display has time to boot up */ |
nuclear@0 | 149 _delay_ms(20); |
nuclear@0 | 150 |
nuclear@0 | 151 clear_bit(BIT_RW); |
nuclear@0 | 152 |
nuclear@0 | 153 clear_bit(BIT_E); |
nuclear@0 | 154 clear_bit(BIT_RS); |
nuclear@0 | 155 #if LCD_BUS_WIDTH == 8 |
nuclear@0 | 156 lcd_write_byte(CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8); |
nuclear@0 | 157 #else |
nuclear@0 | 158 lcd_write_byte(CMD_FUNC | FUNC_BUS_4BIT | FUNC_LINES_2 | FUNC_FONT_5x8); |
nuclear@0 | 159 #endif |
nuclear@0 | 160 enable(); |
nuclear@0 | 161 lcd_wait_busy(); |
nuclear@0 | 162 |
nuclear@0 | 163 clear_bit(BIT_RS); |
nuclear@0 | 164 lcd_write_byte(CMD_ONOFF | ONOFF_DISP); |
nuclear@0 | 165 enable(); |
nuclear@0 | 166 lcd_wait_busy(); |
nuclear@0 | 167 |
nuclear@0 | 168 clear_bit(BIT_RS); |
nuclear@0 | 169 lcd_write_byte(CMD_ENTRY_MODE | (1 << 1)); |
nuclear@0 | 170 enable(); |
nuclear@0 | 171 lcd_wait_busy(); |
nuclear@0 | 172 } |
nuclear@0 | 173 |
nuclear@0 | 174 void lcd_clear(void) |
nuclear@0 | 175 { |
nuclear@0 | 176 clear_bit(BIT_RW); |
nuclear@0 | 177 |
nuclear@0 | 178 clear_bit(BIT_E); |
nuclear@0 | 179 clear_bit(BIT_RS); |
nuclear@0 | 180 lcd_write_byte(CMD_CLEAR); |
nuclear@0 | 181 enable(); |
nuclear@0 | 182 lcd_wait_busy(); |
nuclear@0 | 183 } |
nuclear@0 | 184 |
nuclear@0 | 185 void lcd_set_cursor_addr(unsigned int addr) |
nuclear@0 | 186 { |
nuclear@0 | 187 clear_bit(BIT_RW); |
nuclear@0 | 188 |
nuclear@0 | 189 clear_bit(BIT_E); |
nuclear@0 | 190 clear_bit(BIT_RS); |
nuclear@0 | 191 lcd_write_byte(CMD_DDRAM_ADDR | addr); |
nuclear@0 | 192 enable(); |
nuclear@0 | 193 lcd_wait_busy(); |
nuclear@0 | 194 } |
nuclear@0 | 195 |
nuclear@0 | 196 void lcd_putchar(char c) |
nuclear@0 | 197 { |
nuclear@0 | 198 clear_bit(BIT_RW); |
nuclear@0 | 199 |
nuclear@0 | 200 set_bit(BIT_RS); |
nuclear@0 | 201 lcd_write_byte(c); |
nuclear@0 | 202 enable(); |
nuclear@0 | 203 lcd_wait_busy(); |
nuclear@0 | 204 } |
nuclear@0 | 205 |
nuclear@0 | 206 void lcd_putstr(const char *str) |
nuclear@0 | 207 { |
nuclear@0 | 208 while(*str) { |
nuclear@0 | 209 lcd_putchar(*str++); |
nuclear@0 | 210 } |
nuclear@0 | 211 } |
nuclear@0 | 212 |
nuclear@0 | 213 int lcd_stream_write(char c, FILE *fp) |
nuclear@0 | 214 { |
nuclear@0 | 215 /* TODO terminal shit handling */ |
nuclear@0 | 216 lcd_putchar(c); |
nuclear@0 | 217 return 0; |
nuclear@0 | 218 } |
nuclear@0 | 219 |
nuclear@0 | 220 void lcd_wait_busy(void) |
nuclear@0 | 221 { |
nuclear@0 | 222 unsigned char data; |
nuclear@0 | 223 |
nuclear@0 | 224 do { |
nuclear@0 | 225 NSDELAY(); |
nuclear@0 | 226 clear_bit(BIT_E); |
nuclear@0 | 227 clear_bit(BIT_RS); |
nuclear@0 | 228 set_bit(BIT_RW); |
nuclear@0 | 229 /*PIND = 0xff;*/ |
nuclear@0 | 230 |
nuclear@0 | 231 NSDELAY(); |
nuclear@0 | 232 set_bit(BIT_E); |
nuclear@0 | 233 NSDELAY(); |
nuclear@0 | 234 data = lcd_read_byte(); |
nuclear@0 | 235 clear_bit(BIT_E); |
nuclear@0 | 236 clear_bit(BIT_RW); |
nuclear@0 | 237 |
nuclear@0 | 238 } while(data & (1 << 7)); |
nuclear@0 | 239 } |
nuclear@0 | 240 |
nuclear@0 | 241 static void enable(void) |
nuclear@0 | 242 { |
nuclear@0 | 243 NSDELAY(); |
nuclear@0 | 244 set_bit(BIT_E); |
nuclear@0 | 245 NSDELAY(); |
nuclear@0 | 246 clear_bit(BIT_E); |
nuclear@0 | 247 NSDELAY(); |
nuclear@0 | 248 } |
nuclear@0 | 249 |
nuclear@0 | 250 static void set_bit(int bit) |
nuclear@0 | 251 { |
nuclear@0 | 252 PORTC |= 1 << bit; |
nuclear@0 | 253 } |
nuclear@0 | 254 |
nuclear@0 | 255 static void clear_bit(int bit) |
nuclear@0 | 256 { |
nuclear@0 | 257 PORTC &= ~(1 << bit); |
nuclear@0 | 258 } |
nuclear@0 | 259 |
nuclear@0 | 260 |
nuclear@0 | 261 void delay(int x) |
nuclear@0 | 262 { |
nuclear@0 | 263 int i, j; |
nuclear@0 | 264 |
nuclear@0 | 265 while(x-- > 0) { |
nuclear@0 | 266 for(i=0; i<90; i++) { |
nuclear@0 | 267 for(j=0; j<6; j++) { |
nuclear@0 | 268 asm volatile("nop"); |
nuclear@0 | 269 } |
nuclear@0 | 270 } |
nuclear@0 | 271 } |
nuclear@0 | 272 } |