pwcdecode

changeset 0:050c04723d37

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 01 Nov 2013 09:40:20 +0200
parents
children 4ea5d2920f89
files .hgignore Makefile pwcdecode.c
diffstat 3 files changed, 312 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Fri Nov 01 09:40:20 2013 +0200
     1.3 @@ -0,0 +1,6 @@
     1.4 +\.swp$
     1.5 +\.o$
     1.6 +\.hex$
     1.7 +\.eep$
     1.8 +\.map$
     1.9 +^pwcdecode$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Fri Nov 01 09:40:20 2013 +0200
     2.3 @@ -0,0 +1,34 @@
     2.4 +src = $(wildcard *.c)
     2.5 +obj = $(src:.c=.o)
     2.6 +bin = pwcdecode
     2.7 +hex = $(bin).hex
     2.8 +eep = $(bin).eep
     2.9 +
    2.10 +mcu_gcc = atmega168
    2.11 +mcu_dude = m168
    2.12 +
    2.13 +CC = avr-gcc
    2.14 +OBJCOPY = avr-objcopy
    2.15 +
    2.16 +CFLAGS = -O2 -pedantic -Wall -mmcu=$(mcu_gcc)
    2.17 +LDFLAGS = -Wl,-Map,$(bin).map -mmcu=$(mcu_gcc) -Wl,-u,vfprintf -lprintf_flt -lm
    2.18 +
    2.19 +.PHONY: all
    2.20 +all: $(hex) $(eep)
    2.21 +
    2.22 +$(bin): $(obj)
    2.23 +	$(CC) -o $@ $(obj) $(LDFLAGS)
    2.24 +
    2.25 +$(hex): $(bin)
    2.26 +	$(OBJCOPY) -j .text -j .data -O ihex -R .eeprom $< $@
    2.27 +
    2.28 +$(eep): $(bin)
    2.29 +	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
    2.30 +
    2.31 +.PHONY: program
    2.32 +program: $(hex)
    2.33 +	avrdude -c usbtiny -p $(mcu_dude) -e -U flash:w:$(hex)
    2.34 +
    2.35 +.PHONY: clean
    2.36 +clean:
    2.37 +	rm -f $(bin) $(obj) $(hex) $(eep) $(bin).map
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/pwcdecode.c	Fri Nov 01 09:40:20 2013 +0200
     3.3 @@ -0,0 +1,272 @@
     3.4 +#define F_CLK	1000000
     3.5 +#define F_CPU	1000000
     3.6 +
     3.7 +#include <stdio.h>
     3.8 +#include <avr/io.h>
     3.9 +#include <avr/interrupt.h>
    3.10 +#include <util/delay.h>
    3.11 +
    3.12 +/* hardware setup
    3.13 + * - PORT D: data bits
    3.14 + * - PORT C
    3.15 + *     bit 3: RS
    3.16 + *     bit 4: R/W
    3.17 + *     bit 5: E
    3.18 + */
    3.19 +#define LCD_BUS_WIDTH	8
    3.20 +
    3.21 +#define BIT_RS	3
    3.22 +#define BIT_RW	4
    3.23 +#define BIT_E	5
    3.24 +
    3.25 +#define CMD_CLEAR		1
    3.26 +#define CMD_RET			(1 << 1)
    3.27 +#define CMD_ENTRY_MODE	(1 << 2)
    3.28 +#define CMD_ONOFF		(1 << 3)
    3.29 +#define CMD_SHIFT		(1 << 4)
    3.30 +#define CMD_FUNC		(1 << 5)
    3.31 +#define CMD_CGRAM_ADDR	(1 << 6)
    3.32 +#define CMD_DDRAM_ADDR	(1 << 7)
    3.33 +
    3.34 +#define FUNC_BUS_4BIT	0
    3.35 +#define FUNC_BUS_8BIT	(1 << 4)
    3.36 +#define FUNC_LINES_1	0
    3.37 +#define FUNC_LINES_2	(1 << 3)
    3.38 +#define FUNC_FONT_5x8	0
    3.39 +#define FUNC_FONT_5x11	(1 << 2)
    3.40 +
    3.41 +#define ONOFF_DISP			(1 << 2)
    3.42 +#define ONOFF_CURSOR		(1 << 1)
    3.43 +#define ONOFF_CURSOR_POS	1
    3.44 +
    3.45 +void lcd_init(void);
    3.46 +void lcd_clear(void);
    3.47 +void lcd_set_cursor_addr(unsigned int addr);
    3.48 +void lcd_putchar(char c);
    3.49 +void lcd_putstr(const char *str);
    3.50 +int lcd_stream_write(char c, FILE *fp);
    3.51 +void lcd_wait_busy(void);
    3.52 +static void enable(void);
    3.53 +static void set_bit(int bit);
    3.54 +static void clear_bit(int bit);
    3.55 +void delay(int x);
    3.56 +
    3.57 +#define NSDELAY()	asm volatile ("nop")
    3.58 +#define DEBUG(i)	(PORTB = (1 << (i)))
    3.59 +
    3.60 +FILE stream_lcd = FDEV_SETUP_STREAM(lcd_stream_write, NULL, _FDEV_SETUP_WRITE);
    3.61 +
    3.62 +unsigned int pulse_time;
    3.63 +
    3.64 +int main(void)
    3.65 +{
    3.66 +	stdout = stderr = &stream_lcd;
    3.67 +
    3.68 +	DDRB = 0;	/* set port B as input (bit 0 is used to measure pulse width) */
    3.69 +	PORTB = 0;	/* disable pullups */
    3.70 +
    3.71 +	DDRD = 0xff;
    3.72 +	DDRC = 0xfe;
    3.73 +	PORTC = 0;	/* disable pullups */
    3.74 +
    3.75 +	lcd_init();
    3.76 +	lcd_clear();
    3.77 +
    3.78 +	printf("initializing...");
    3.79 +
    3.80 +	TCCR1B |= (1 << ICES1);	/* set first capture to occur on a rising edge */
    3.81 +	TCCR1B = (TCCR1B & 0xf8) | 1;	/* no prescaling */
    3.82 +	TIMSK1 |= (1 << ICIE1);	/* enable timer1 input capture interrupt */
    3.83 +	sei();
    3.84 +
    3.85 +	for(;;) {
    3.86 +		static int blink = 0;
    3.87 +
    3.88 +		PORTB = blink ? 1 : 0;
    3.89 +		blink = (blink + 1) & 1;
    3.90 +
    3.91 +		lcd_set_cursor_addr(0);
    3.92 +		printf("pulse time: %u us  ", pulse_time);
    3.93 +		lcd_set_cursor_addr(64);
    3.94 +		printf("pos: %u%%          ", (pulse_time - 1000) / 10);
    3.95 +		_delay_ms(100);
    3.96 +	}
    3.97 +	return 0;
    3.98 +}
    3.99 +
   3.100 +ISR(TIMER1_CAPT_vect)
   3.101 +{
   3.102 +	static int rising;
   3.103 +
   3.104 +	rising = !rising;
   3.105 +	if(rising) {
   3.106 +		/* rising edge: reset the timer */
   3.107 +		TCNT1 = 0;
   3.108 +		/* and set a falling edge trigger */
   3.109 +		TCCR1B &= ~(1 << ICES1);
   3.110 +	} else {
   3.111 +		/* falling edge: calculate the time since the last rise */
   3.112 +		pulse_time = ICR1;
   3.113 +		/* and set a rising edge trigger */
   3.114 +		TCCR1B |= 1 << ICES1;
   3.115 +	}
   3.116 +}
   3.117 +
   3.118 +void lcd_write_byte(unsigned char byte)
   3.119 +{
   3.120 +#if LCD_BUS_WIDTH == 8
   3.121 +	DDRD = 0xff;
   3.122 +	PORTD = byte;
   3.123 +#else
   3.124 +	DDRD = (DDRD & 0xf0) | 0xf;
   3.125 +
   3.126 +	PORTD = (PORTD & 0xf0) | ((byte >> 4) & 0xf);
   3.127 +	PORTD = (PORTD & 0xf0) | (byte & 0xf);
   3.128 +#endif
   3.129 +}
   3.130 +
   3.131 +unsigned char lcd_read_byte(void)
   3.132 +{
   3.133 +#if LCD_BUS_WIDTH == 8
   3.134 +	DDRD = 0;
   3.135 +	PORTD = 0;	/* disable pull-ups */
   3.136 +
   3.137 +	return PIND;
   3.138 +#else
   3.139 +	unsigned char byte;
   3.140 +
   3.141 +	DDRD = DDRD & 0xf0;
   3.142 +	PORTD &= 0xf0;	/* disable pull-ups */
   3.143 +
   3.144 +	byte = (PIND & 0xf) << 4;
   3.145 +	return byte | (PIND & 0xf);
   3.146 +#endif
   3.147 +}
   3.148 +
   3.149 +void lcd_init(void)
   3.150 +{
   3.151 +	/* make sure the display has time to boot up */
   3.152 +	_delay_ms(20);
   3.153 +
   3.154 +	clear_bit(BIT_RW);
   3.155 +
   3.156 +	clear_bit(BIT_E);
   3.157 +	clear_bit(BIT_RS);
   3.158 +#if LCD_BUS_WIDTH == 8
   3.159 +	lcd_write_byte(CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
   3.160 +#else
   3.161 +	lcd_write_byte(CMD_FUNC | FUNC_BUS_4BIT | FUNC_LINES_2 | FUNC_FONT_5x8);
   3.162 +#endif
   3.163 +	enable();
   3.164 +	lcd_wait_busy();
   3.165 +
   3.166 +	clear_bit(BIT_RS);
   3.167 +	lcd_write_byte(CMD_ONOFF | ONOFF_DISP);
   3.168 +	enable();
   3.169 +	lcd_wait_busy();
   3.170 +
   3.171 +	clear_bit(BIT_RS);
   3.172 +	lcd_write_byte(CMD_ENTRY_MODE | (1 << 1));
   3.173 +	enable();
   3.174 +	lcd_wait_busy();
   3.175 +}
   3.176 +
   3.177 +void lcd_clear(void)
   3.178 +{
   3.179 +	clear_bit(BIT_RW);
   3.180 +
   3.181 +	clear_bit(BIT_E);
   3.182 +	clear_bit(BIT_RS);
   3.183 +	lcd_write_byte(CMD_CLEAR);
   3.184 +	enable();
   3.185 +	lcd_wait_busy();
   3.186 +}
   3.187 +
   3.188 +void lcd_set_cursor_addr(unsigned int addr)
   3.189 +{
   3.190 +	clear_bit(BIT_RW);
   3.191 +
   3.192 +	clear_bit(BIT_E);
   3.193 +	clear_bit(BIT_RS);
   3.194 +	lcd_write_byte(CMD_DDRAM_ADDR | addr);
   3.195 +	enable();
   3.196 +	lcd_wait_busy();
   3.197 +}
   3.198 +
   3.199 +void lcd_putchar(char c)
   3.200 +{
   3.201 +	clear_bit(BIT_RW);
   3.202 +
   3.203 +	set_bit(BIT_RS);
   3.204 +	lcd_write_byte(c);
   3.205 +	enable();
   3.206 +	lcd_wait_busy();
   3.207 +}
   3.208 +
   3.209 +void lcd_putstr(const char *str)
   3.210 +{
   3.211 +	while(*str) {
   3.212 +		lcd_putchar(*str++);
   3.213 +	}
   3.214 +}
   3.215 +
   3.216 +int lcd_stream_write(char c, FILE *fp)
   3.217 +{
   3.218 +	/* TODO terminal shit handling */
   3.219 +	lcd_putchar(c);
   3.220 +	return 0;
   3.221 +}
   3.222 +
   3.223 +void lcd_wait_busy(void)
   3.224 +{
   3.225 +	unsigned char data;
   3.226 +
   3.227 +	do {
   3.228 +		NSDELAY();
   3.229 +		clear_bit(BIT_E);
   3.230 +		clear_bit(BIT_RS);
   3.231 +		set_bit(BIT_RW);
   3.232 +		/*PIND = 0xff;*/
   3.233 +
   3.234 +		NSDELAY();
   3.235 +		set_bit(BIT_E);
   3.236 +		NSDELAY();
   3.237 +		data = lcd_read_byte();
   3.238 +		clear_bit(BIT_E);
   3.239 +		clear_bit(BIT_RW);
   3.240 +
   3.241 +	} while(data & (1 << 7));
   3.242 +}
   3.243 +
   3.244 +static void enable(void)
   3.245 +{
   3.246 +	NSDELAY();
   3.247 +	set_bit(BIT_E);
   3.248 +	NSDELAY();
   3.249 +	clear_bit(BIT_E);
   3.250 +	NSDELAY();
   3.251 +}
   3.252 +
   3.253 +static void set_bit(int bit)
   3.254 +{
   3.255 +	PORTC |= 1 << bit;
   3.256 +}
   3.257 +
   3.258 +static void clear_bit(int bit)
   3.259 +{
   3.260 +	PORTC &= ~(1 << bit);
   3.261 +}
   3.262 +
   3.263 +
   3.264 +void delay(int x)
   3.265 +{
   3.266 +	int i, j;
   3.267 +
   3.268 +	while(x-- > 0) {
   3.269 +		for(i=0; i<90; i++) {
   3.270 +			for(j=0; j<6; j++) {
   3.271 +				asm volatile("nop");
   3.272 +			}
   3.273 +		}
   3.274 +	}
   3.275 +}