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 }