# HG changeset patch # User John Tsiombikas # Date 1404885526 -10800 # Node ID b1d590a201dfaea128a3696a4db61a71046694f2 initial commit diff -r 000000000000 -r b1d590a201df .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Jul 09 08:58:46 2014 +0300 @@ -0,0 +1,7 @@ +\.o$ +\.d$ +\.swp$ +\.hex$ +\.eep$ +\.map$ +^equeue$ diff -r 000000000000 -r b1d590a201df Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Wed Jul 09 08:58:46 2014 +0300 @@ -0,0 +1,38 @@ +src = $(wildcard *.c) +obj = $(src:.c=.o) +bin = equeue +hex = $(bin).hex +eep = $(bin).eep + +mcu_gcc = atmega168 +mcu_dude = m168 + +CC = avr-gcc +OBJCOPY = avr-objcopy + +CFLAGS = -O2 -pedantic -Wall -mmcu=$(mcu_gcc) -DXTAL=14745600 +LDFLAGS = -Wl,-Map,$(bin).map -mmcu=$(mcu_gcc) -lprintf_min + +.PHONY: all +all: $(hex) $(eep) + +$(bin): $(obj) + $(CC) -o $@ $(obj) $(LDFLAGS) + +$(hex): $(bin) + $(OBJCOPY) -j .text -j .data -O ihex -R .eeprom $< $@ + +$(eep): $(bin) + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ + +.PHONY: fuses +fuses: + avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0xc7:m + +.PHONY: program +program: $(hex) + avrdude -c usbtiny -p $(mcu_dude) -e -U flash:w:$(hex) + +.PHONY: clean +clean: + rm -f $(bin) $(obj) $(hex) $(eep) $(bin).map diff -r 000000000000 -r b1d590a201df equeue.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/equeue.c Wed Jul 09 08:58:46 2014 +0300 @@ -0,0 +1,225 @@ +/* pin assignments + * C[0,5] 7seg [a,f] + * B1 7seg g + * B0 select display (0: units, 1: tens) + * B[2,3] buttons with internal pullups + * D[6,7] mode leds + */ + +#ifdef XTAL +#define F_CLK XTAL +#define F_CPU XTAL +#else +#define F_CLK 1000000 +#define F_CPU 1000000 +#endif + +#include +#include +#include +#include +#include "serial.h" + +#define SHOW_TICKET_DELAY 256 + +#define BN_NEXT 2 +#define BN_TICKET 3 + +#define LED_MODE_CUR 6 +#define LED_MODE_TICKET 7 + +void show(int num, int digit); +void disp_off(void); +void runcmd(const char *cmd); + +int show_ticket_cnt; +int cur_customer; +int last_ticket; + +#define MAX_INPUT_SIZE 256 +char input[MAX_INPUT_SIZE]; +int inp_cidx; + +int cmd_echo = 1; + +int main(void) +{ + int i = 0; + + DDRB = 0xf3; /* B: output except [2,3] */ + DDRC = 0xff; /* C: output */ + DDRD = 0xff; /* D: output */ + + PORTB = 0xff; /* activate pullups and whatever */ + PORTC = 0xff; + PORTD = 1 << LED_MODE_CUR; + + PCICR = (1 << PCIE0); /* enable pin change interrupt 2 */ + PCMSK0 = (1 << PCINT2) | (1 << PCINT3); + + init_serial(); + + sei(); + + for(;;) { + int digit = i & 1; + + /* first grab any input from the serial port */ + while(have_input()) { + int c = getchar(); + if(cmd_echo) { + putchar(c); /* echo back */ + } + if(c == '\r' || c == '\n') { + input[inp_cidx] = 0; + runcmd(input); + inp_cidx = 0; + } else { + input[inp_cidx++] = c; + } + } + + disp_off(); + _delay_ms(1); + PORTB = (PORTB & 0xfe) | digit; + /*PORTD = (PORTD & 0xdf) | ((~digit) << 5);*/ + _delay_ms(1); + + if(show_ticket_cnt > 0) { + --show_ticket_cnt; + show(last_ticket, digit); + PORTD = (PORTD & 0x3f) | (1 << LED_MODE_TICKET); + } else { + show(cur_customer, digit); + PORTD = (PORTD & 0x3f) | (1 << LED_MODE_CUR); + } + + ++i; + _delay_ms(1); + } +} + +void issue_ticket(void) +{ + last_ticket++; + show_ticket_cnt = SHOW_TICKET_DELAY; + printf("ticket: %d\n", last_ticket); +} + +void next_customer(void) +{ + if(cur_customer < last_ticket) { + cur_customer++; + show_ticket_cnt = 0; + printf("customer: %d\n", cur_customer); + } +} + +ISR(PCINT0_vect) +{ + unsigned char inp = PINB; + + if((inp & (1 << BN_TICKET)) == 0) { + /* customer pressed the ticket button */ + issue_ticket(); + } + if((inp & (1 << BN_NEXT)) == 0) { + /* teller pressed the next customer button */ + next_customer(); + } +} + +enum { + SEG_A = 1 << 0, + SEG_B = 1 << 1, + SEG_C = 1 << 2, + SEG_D = 1 << 3, + SEG_E = 1 << 4, + SEG_F = 1 << 5, + SEG_G = 1 << 6 +}; + +static const unsigned char seg[] = { + SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, /* 0 */ + SEG_B | SEG_C, /* 1 */ + SEG_A | SEG_B | SEG_G | SEG_E | SEG_D, /* 2 */ + SEG_A | SEG_B | SEG_G | SEG_C | SEG_D, /* 3 */ + SEG_F | SEG_B | SEG_G | SEG_C, /* 4 */ + SEG_A | SEG_F | SEG_G | SEG_C | SEG_D, /* 5 */ + SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D, /* 6 */ + SEG_A | SEG_B | SEG_C, /* 7 */ + 0xff, /* 8 */ + SEG_A | SEG_B | SEG_F | SEG_G | SEG_C | SEG_D, /* 9 */ + 0 +}; + +void show(int num, int digit) +{ + int i, x = num; + unsigned int bits; + + for(i=0; i> 5) & 2); +} + +void disp_off(void) +{ + PORTC = PORTC & 0xc0; + PORTB = PORTB & 0xfd; +} + +#define VERSTR \ + "Queue system v0.1 by John Tsiombikas " + +void runcmd(const char *cmd) +{ + switch(cmd[0]) { + case 'e': + cmd_echo = !cmd_echo; + printf("OK,turning echo %s\n", cmd_echo ? "on" : "off"); + break; + + case 'v': + printf("OK,%s\n", VERSTR); + break; + + case 'r': + printf("OK,reseting queues\n"); + cur_customer = 0; + last_ticket = 0; + show_ticket_cnt = 0; + break; + + case 't': + printf("OK,ticket: %d\n", last_ticket); + break; + + case 'c': + printf("OK,customer: %d\n", cur_customer); + break; + + case 'q': + printf("OK,issuing queue ticket\n"); + issue_ticket(); + break; + + case 'n': + printf("OK,next customer\n"); + next_customer(); + break; + + case 'h': + printf("OK,commands: (e)cho, (v)ersion, (t)icket, (c)ustomer, " + "(n)ext, (q)ueue, (r)eset, (h)elp.\n"); + break; + + default: + printf("ERR,unknown command: %s\n", cmd); + } +} diff -r 000000000000 -r b1d590a201df runterm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runterm Wed Jul 09 08:58:46 2014 +0300 @@ -0,0 +1,1 @@ +minicom -b 9600 -D /dev/ttyUSB0 -o diff -r 000000000000 -r b1d590a201df serial.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serial.c Wed Jul 09 08:58:46 2014 +0300 @@ -0,0 +1,104 @@ +#define F_CLK XTAL +#define F_CPU XTAL + +#include +#include +#include +#include + +#define BAUD 9600 +#define UBRR_VAL (F_CLK / 16 / BAUD - 1) + +static int uart_send_char(char c, FILE *fp); +static int uart_get_char(FILE *fp); + +#define BUF_SZ 32 +static char outbuf[BUF_SZ]; +static volatile int out_rd, out_wr; + +static char inbuf[BUF_SZ]; +static volatile int in_rd, in_wr; + +static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW); + + + +void init_serial(void) +{ + power_usart0_enable(); + + /* make RXD (D0) an input and TXD (D1) an output */ + DDRD = (DDRD & 0xfc) | 2; + + /* set baud generator timer reset value */ + UBRR0H = (unsigned char)(UBRR_VAL >> 8); + UBRR0L = (unsigned char)UBRR_VAL; + + /* enable rx/tx and recv interrupt */ + UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); + /* set frame format: 8n1 */ + UCSR0C = 3 << UCSZ00; + + stdin = stdout = stderr = &std_stream; +} + +int have_input(void) +{ + return in_wr != in_rd; +} + +#define NEXT_IDX(x) (((x) + 1) % BUF_SZ) +static int uart_send_char(char c, FILE *fp) +{ + int next; + + if(c == '\n') { + uart_send_char('\r', fp); + } + + next = NEXT_IDX(out_wr); + while(next == out_rd); + + outbuf[out_wr] = c; + out_wr = next; + + /* enable the Tx data register empty interrupt */ + UCSR0B |= 1 << UDRIE0; + return 0; +} + +static int uart_get_char(FILE *fp) +{ + char c; + int next = NEXT_IDX(in_rd); + + while(in_rd == in_wr); + + c = inbuf[in_rd]; + in_rd = next; + return c; +} + +ISR(USART_RX_vect) +{ + char c = UDR0; + + if(c == '\r') { + c = '\n'; + } + + inbuf[in_wr] = c; + in_wr = NEXT_IDX(in_wr); +} + +/* USART Tx data register empty (can send more data) */ +ISR(USART_UDRE_vect) +{ + if(out_rd != out_wr) { + UDR0 = outbuf[out_rd]; + out_rd = NEXT_IDX(out_rd); + } else { + /* no more data to send for now, disable the interrupt */ + UCSR0B &= ~(1 << UDRIE0); + } +} diff -r 000000000000 -r b1d590a201df serial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serial.h Wed Jul 09 08:58:46 2014 +0300 @@ -0,0 +1,7 @@ +#ifndef SERIAL_H_ +#define SERIAL_H_ + +void init_serial(void); +int have_input(void); + +#endif /* SERIAL_H_ */