avr-equeue
changeset 0:b1d590a201df
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 09 Jul 2014 08:58:46 +0300 |
parents | |
children | 9cb1db5d0e7c |
files | .hgignore Makefile equeue.c runterm serial.c serial.h |
diffstat | 6 files changed, 382 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Wed Jul 09 08:58:46 2014 +0300 1.3 @@ -0,0 +1,7 @@ 1.4 +\.o$ 1.5 +\.d$ 1.6 +\.swp$ 1.7 +\.hex$ 1.8 +\.eep$ 1.9 +\.map$ 1.10 +^equeue$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Wed Jul 09 08:58:46 2014 +0300 2.3 @@ -0,0 +1,38 @@ 2.4 +src = $(wildcard *.c) 2.5 +obj = $(src:.c=.o) 2.6 +bin = equeue 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) -DXTAL=14745600 2.17 +LDFLAGS = -Wl,-Map,$(bin).map -mmcu=$(mcu_gcc) -lprintf_min 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: fuses 2.32 +fuses: 2.33 + avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0xc7:m 2.34 + 2.35 +.PHONY: program 2.36 +program: $(hex) 2.37 + avrdude -c usbtiny -p $(mcu_dude) -e -U flash:w:$(hex) 2.38 + 2.39 +.PHONY: clean 2.40 +clean: 2.41 + rm -f $(bin) $(obj) $(hex) $(eep) $(bin).map
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/equeue.c Wed Jul 09 08:58:46 2014 +0300 3.3 @@ -0,0 +1,225 @@ 3.4 +/* pin assignments 3.5 + * C[0,5] 7seg [a,f] 3.6 + * B1 7seg g 3.7 + * B0 select display (0: units, 1: tens) 3.8 + * B[2,3] buttons with internal pullups 3.9 + * D[6,7] mode leds 3.10 + */ 3.11 + 3.12 +#ifdef XTAL 3.13 +#define F_CLK XTAL 3.14 +#define F_CPU XTAL 3.15 +#else 3.16 +#define F_CLK 1000000 3.17 +#define F_CPU 1000000 3.18 +#endif 3.19 + 3.20 +#include <stdio.h> 3.21 +#include <avr/io.h> 3.22 +#include <avr/interrupt.h> 3.23 +#include <util/delay.h> 3.24 +#include "serial.h" 3.25 + 3.26 +#define SHOW_TICKET_DELAY 256 3.27 + 3.28 +#define BN_NEXT 2 3.29 +#define BN_TICKET 3 3.30 + 3.31 +#define LED_MODE_CUR 6 3.32 +#define LED_MODE_TICKET 7 3.33 + 3.34 +void show(int num, int digit); 3.35 +void disp_off(void); 3.36 +void runcmd(const char *cmd); 3.37 + 3.38 +int show_ticket_cnt; 3.39 +int cur_customer; 3.40 +int last_ticket; 3.41 + 3.42 +#define MAX_INPUT_SIZE 256 3.43 +char input[MAX_INPUT_SIZE]; 3.44 +int inp_cidx; 3.45 + 3.46 +int cmd_echo = 1; 3.47 + 3.48 +int main(void) 3.49 +{ 3.50 + int i = 0; 3.51 + 3.52 + DDRB = 0xf3; /* B: output except [2,3] */ 3.53 + DDRC = 0xff; /* C: output */ 3.54 + DDRD = 0xff; /* D: output */ 3.55 + 3.56 + PORTB = 0xff; /* activate pullups and whatever */ 3.57 + PORTC = 0xff; 3.58 + PORTD = 1 << LED_MODE_CUR; 3.59 + 3.60 + PCICR = (1 << PCIE0); /* enable pin change interrupt 2 */ 3.61 + PCMSK0 = (1 << PCINT2) | (1 << PCINT3); 3.62 + 3.63 + init_serial(); 3.64 + 3.65 + sei(); 3.66 + 3.67 + for(;;) { 3.68 + int digit = i & 1; 3.69 + 3.70 + /* first grab any input from the serial port */ 3.71 + while(have_input()) { 3.72 + int c = getchar(); 3.73 + if(cmd_echo) { 3.74 + putchar(c); /* echo back */ 3.75 + } 3.76 + if(c == '\r' || c == '\n') { 3.77 + input[inp_cidx] = 0; 3.78 + runcmd(input); 3.79 + inp_cidx = 0; 3.80 + } else { 3.81 + input[inp_cidx++] = c; 3.82 + } 3.83 + } 3.84 + 3.85 + disp_off(); 3.86 + _delay_ms(1); 3.87 + PORTB = (PORTB & 0xfe) | digit; 3.88 + /*PORTD = (PORTD & 0xdf) | ((~digit) << 5);*/ 3.89 + _delay_ms(1); 3.90 + 3.91 + if(show_ticket_cnt > 0) { 3.92 + --show_ticket_cnt; 3.93 + show(last_ticket, digit); 3.94 + PORTD = (PORTD & 0x3f) | (1 << LED_MODE_TICKET); 3.95 + } else { 3.96 + show(cur_customer, digit); 3.97 + PORTD = (PORTD & 0x3f) | (1 << LED_MODE_CUR); 3.98 + } 3.99 + 3.100 + ++i; 3.101 + _delay_ms(1); 3.102 + } 3.103 +} 3.104 + 3.105 +void issue_ticket(void) 3.106 +{ 3.107 + last_ticket++; 3.108 + show_ticket_cnt = SHOW_TICKET_DELAY; 3.109 + printf("ticket: %d\n", last_ticket); 3.110 +} 3.111 + 3.112 +void next_customer(void) 3.113 +{ 3.114 + if(cur_customer < last_ticket) { 3.115 + cur_customer++; 3.116 + show_ticket_cnt = 0; 3.117 + printf("customer: %d\n", cur_customer); 3.118 + } 3.119 +} 3.120 + 3.121 +ISR(PCINT0_vect) 3.122 +{ 3.123 + unsigned char inp = PINB; 3.124 + 3.125 + if((inp & (1 << BN_TICKET)) == 0) { 3.126 + /* customer pressed the ticket button */ 3.127 + issue_ticket(); 3.128 + } 3.129 + if((inp & (1 << BN_NEXT)) == 0) { 3.130 + /* teller pressed the next customer button */ 3.131 + next_customer(); 3.132 + } 3.133 +} 3.134 + 3.135 +enum { 3.136 + SEG_A = 1 << 0, 3.137 + SEG_B = 1 << 1, 3.138 + SEG_C = 1 << 2, 3.139 + SEG_D = 1 << 3, 3.140 + SEG_E = 1 << 4, 3.141 + SEG_F = 1 << 5, 3.142 + SEG_G = 1 << 6 3.143 +}; 3.144 + 3.145 +static const unsigned char seg[] = { 3.146 + SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, /* 0 */ 3.147 + SEG_B | SEG_C, /* 1 */ 3.148 + SEG_A | SEG_B | SEG_G | SEG_E | SEG_D, /* 2 */ 3.149 + SEG_A | SEG_B | SEG_G | SEG_C | SEG_D, /* 3 */ 3.150 + SEG_F | SEG_B | SEG_G | SEG_C, /* 4 */ 3.151 + SEG_A | SEG_F | SEG_G | SEG_C | SEG_D, /* 5 */ 3.152 + SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D, /* 6 */ 3.153 + SEG_A | SEG_B | SEG_C, /* 7 */ 3.154 + 0xff, /* 8 */ 3.155 + SEG_A | SEG_B | SEG_F | SEG_G | SEG_C | SEG_D, /* 9 */ 3.156 + 0 3.157 +}; 3.158 + 3.159 +void show(int num, int digit) 3.160 +{ 3.161 + int i, x = num; 3.162 + unsigned int bits; 3.163 + 3.164 + for(i=0; i<digit; i++) { 3.165 + x /= 10; 3.166 + } 3.167 + x %= 10; 3.168 + bits = seg[x]; 3.169 + 3.170 + PORTC = (PORTC & 0xc0) | (bits & 0x3f); 3.171 + PORTB = (PORTB & 0xfd) | ((bits >> 5) & 2); 3.172 +} 3.173 + 3.174 +void disp_off(void) 3.175 +{ 3.176 + PORTC = PORTC & 0xc0; 3.177 + PORTB = PORTB & 0xfd; 3.178 +} 3.179 + 3.180 +#define VERSTR \ 3.181 + "Queue system v0.1 by John Tsiombikas <nuclear@member.fsf.org>" 3.182 + 3.183 +void runcmd(const char *cmd) 3.184 +{ 3.185 + switch(cmd[0]) { 3.186 + case 'e': 3.187 + cmd_echo = !cmd_echo; 3.188 + printf("OK,turning echo %s\n", cmd_echo ? "on" : "off"); 3.189 + break; 3.190 + 3.191 + case 'v': 3.192 + printf("OK,%s\n", VERSTR); 3.193 + break; 3.194 + 3.195 + case 'r': 3.196 + printf("OK,reseting queues\n"); 3.197 + cur_customer = 0; 3.198 + last_ticket = 0; 3.199 + show_ticket_cnt = 0; 3.200 + break; 3.201 + 3.202 + case 't': 3.203 + printf("OK,ticket: %d\n", last_ticket); 3.204 + break; 3.205 + 3.206 + case 'c': 3.207 + printf("OK,customer: %d\n", cur_customer); 3.208 + break; 3.209 + 3.210 + case 'q': 3.211 + printf("OK,issuing queue ticket\n"); 3.212 + issue_ticket(); 3.213 + break; 3.214 + 3.215 + case 'n': 3.216 + printf("OK,next customer\n"); 3.217 + next_customer(); 3.218 + break; 3.219 + 3.220 + case 'h': 3.221 + printf("OK,commands: (e)cho, (v)ersion, (t)icket, (c)ustomer, " 3.222 + "(n)ext, (q)ueue, (r)eset, (h)elp.\n"); 3.223 + break; 3.224 + 3.225 + default: 3.226 + printf("ERR,unknown command: %s\n", cmd); 3.227 + } 3.228 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/runterm Wed Jul 09 08:58:46 2014 +0300 4.3 @@ -0,0 +1,1 @@ 4.4 +minicom -b 9600 -D /dev/ttyUSB0 -o
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/serial.c Wed Jul 09 08:58:46 2014 +0300 5.3 @@ -0,0 +1,104 @@ 5.4 +#define F_CLK XTAL 5.5 +#define F_CPU XTAL 5.6 + 5.7 +#include <stdio.h> 5.8 +#include <avr/io.h> 5.9 +#include <avr/interrupt.h> 5.10 +#include <avr/power.h> 5.11 + 5.12 +#define BAUD 9600 5.13 +#define UBRR_VAL (F_CLK / 16 / BAUD - 1) 5.14 + 5.15 +static int uart_send_char(char c, FILE *fp); 5.16 +static int uart_get_char(FILE *fp); 5.17 + 5.18 +#define BUF_SZ 32 5.19 +static char outbuf[BUF_SZ]; 5.20 +static volatile int out_rd, out_wr; 5.21 + 5.22 +static char inbuf[BUF_SZ]; 5.23 +static volatile int in_rd, in_wr; 5.24 + 5.25 +static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW); 5.26 + 5.27 + 5.28 + 5.29 +void init_serial(void) 5.30 +{ 5.31 + power_usart0_enable(); 5.32 + 5.33 + /* make RXD (D0) an input and TXD (D1) an output */ 5.34 + DDRD = (DDRD & 0xfc) | 2; 5.35 + 5.36 + /* set baud generator timer reset value */ 5.37 + UBRR0H = (unsigned char)(UBRR_VAL >> 8); 5.38 + UBRR0L = (unsigned char)UBRR_VAL; 5.39 + 5.40 + /* enable rx/tx and recv interrupt */ 5.41 + UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); 5.42 + /* set frame format: 8n1 */ 5.43 + UCSR0C = 3 << UCSZ00; 5.44 + 5.45 + stdin = stdout = stderr = &std_stream; 5.46 +} 5.47 + 5.48 +int have_input(void) 5.49 +{ 5.50 + return in_wr != in_rd; 5.51 +} 5.52 + 5.53 +#define NEXT_IDX(x) (((x) + 1) % BUF_SZ) 5.54 +static int uart_send_char(char c, FILE *fp) 5.55 +{ 5.56 + int next; 5.57 + 5.58 + if(c == '\n') { 5.59 + uart_send_char('\r', fp); 5.60 + } 5.61 + 5.62 + next = NEXT_IDX(out_wr); 5.63 + while(next == out_rd); 5.64 + 5.65 + outbuf[out_wr] = c; 5.66 + out_wr = next; 5.67 + 5.68 + /* enable the Tx data register empty interrupt */ 5.69 + UCSR0B |= 1 << UDRIE0; 5.70 + return 0; 5.71 +} 5.72 + 5.73 +static int uart_get_char(FILE *fp) 5.74 +{ 5.75 + char c; 5.76 + int next = NEXT_IDX(in_rd); 5.77 + 5.78 + while(in_rd == in_wr); 5.79 + 5.80 + c = inbuf[in_rd]; 5.81 + in_rd = next; 5.82 + return c; 5.83 +} 5.84 + 5.85 +ISR(USART_RX_vect) 5.86 +{ 5.87 + char c = UDR0; 5.88 + 5.89 + if(c == '\r') { 5.90 + c = '\n'; 5.91 + } 5.92 + 5.93 + inbuf[in_wr] = c; 5.94 + in_wr = NEXT_IDX(in_wr); 5.95 +} 5.96 + 5.97 +/* USART Tx data register empty (can send more data) */ 5.98 +ISR(USART_UDRE_vect) 5.99 +{ 5.100 + if(out_rd != out_wr) { 5.101 + UDR0 = outbuf[out_rd]; 5.102 + out_rd = NEXT_IDX(out_rd); 5.103 + } else { 5.104 + /* no more data to send for now, disable the interrupt */ 5.105 + UCSR0B &= ~(1 << UDRIE0); 5.106 + } 5.107 +}