diff --git a/apps/ir_spam1/Makefile b/apps/ir_spam1/Makefile new file mode 100644 index 0000000..f751647 --- /dev/null +++ b/apps/ir_spam1/Makefile @@ -0,0 +1,71 @@ +# File: Makefile +# Author: M. P. Hayes, UCECE +# Date: 12 Sep 2010 +# Descr: Makefile for ir_spam1 + +# Definitions. +CC = avr-gcc +CFLAGS = -mmcu=atmega32u2 -Os -Wall -Wstrict-prototypes -Wextra -g -I../../drivers/avr -I../../utils +OBJCOPY = avr-objcopy +SIZE = avr-size +DEL = rm + + +# Default target. +all: ir_spam1.out + + +# Compile: create object files from C source files. +ir_spam1.o: ir_spam1.c ../../drivers/avr/ir_uart.h ../../drivers/avr/system.h ../../utils/pacer.h + $(CC) -c $(CFLAGS) $< -o $@ + +ir_uart.o: ../../drivers/avr/ir_uart.c ../../drivers/avr/ir_uart.h ../../drivers/avr/pio.h ../../drivers/avr/system.h ../../drivers/avr/timer0.h ../../drivers/avr/usart1.h + $(CC) -c $(CFLAGS) $< -o $@ + +pio.o: ../../drivers/avr/pio.c ../../drivers/avr/pio.h ../../drivers/avr/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +prescale.o: ../../drivers/avr/prescale.c ../../drivers/avr/prescale.h ../../drivers/avr/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +system.o: ../../drivers/avr/system.c ../../drivers/avr/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +timer.o: ../../drivers/avr/timer.c ../../drivers/avr/system.h ../../drivers/avr/timer.h + $(CC) -c $(CFLAGS) $< -o $@ + +timer0.o: ../../drivers/avr/timer0.c ../../drivers/avr/bits.h ../../drivers/avr/prescale.h ../../drivers/avr/system.h ../../drivers/avr/timer0.h + $(CC) -c $(CFLAGS) $< -o $@ + +usart1.o: ../../drivers/avr/usart1.c ../../drivers/avr/system.h ../../drivers/avr/usart1.h + $(CC) -c $(CFLAGS) $< -o $@ + +pacer.o: ../../utils/pacer.c ../../drivers/avr/system.h ../../drivers/avr/timer.h ../../utils/pacer.h + $(CC) -c $(CFLAGS) $< -o $@ + + + + +# Link: create output file (executable) from object files. +ir_spam1.out: ir_spam1.o ir_uart.o pio.o prescale.o system.o timer.o timer0.o usart1.o pacer.o + $(CC) $(CFLAGS) $^ -o $@ -lm + $(SIZE) $@ + + +# Create hex file for programming from executable file. +ir_spam1.hex: ir_spam1.out + $(OBJCOPY) -O ihex ir_spam1.out ir_spam1.hex + + +# Target: clean project. +.PHONY: clean +clean: + -$(DEL) *.o *.out *.hex + + +# Target: program project. +.PHONY: program +program: ir_spam1.hex + dfu-programmer atmega32u2 erase; dfu-programmer atmega32u2 flash ir_spam1.hex; dfu-programmer atmega32u2 start + + diff --git a/apps/ir_spam1/Makefile.test b/apps/ir_spam1/Makefile.test new file mode 100644 index 0000000..772517a --- /dev/null +++ b/apps/ir_spam1/Makefile.test @@ -0,0 +1,52 @@ +# File: Makefile +# Author: M. P. Hayes, UCECE +# Date: 11 Sep 2010 +# Descr: Makefile for ir_spam1 + +CC = gcc +CFLAGS = -Wall -Wstrict-prototypes -Wextra -g -I../../drivers/test -I../../utils + +DEL = rm + + +# Default target. +all: ir_spam1 + + +# Compile: create object files from C source files. +ir_spam1-test.o: ir_spam1.c ../../drivers/test/ir_uart.h ../../drivers/test/system.h ../../utils/pacer.h + $(CC) -c $(CFLAGS) $< -o $@ + +ir_uart-test.o: ../../drivers/test/ir_uart.c ../../drivers/test/ir_uart.h ../../drivers/test/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +mgetkey-test.o: ../../drivers/test/mgetkey.c ../../drivers/test/mgetkey.h + $(CC) -c $(CFLAGS) $< -o $@ + +pio-test.o: ../../drivers/test/pio.c ../../drivers/test/avrtest.h ../../drivers/test/pio.h ../../drivers/test/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +system-test.o: ../../drivers/test/system.c ../../drivers/test/avrtest.h ../../drivers/test/mgetkey.h ../../drivers/test/pio.h ../../drivers/test/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +timer-test.o: ../../drivers/test/timer.c ../../drivers/test/system.h ../../drivers/test/timer.h + $(CC) -c $(CFLAGS) $< -o $@ + +pacer-test.o: ../../utils/pacer.c ../../drivers/test/system.h ../../drivers/test/timer.h ../../utils/pacer.h + $(CC) -c $(CFLAGS) $< -o $@ + + + + +# Link: create executable file from object files. +ir_spam1: ir_spam1-test.o ir_uart-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o pacer-test.o + $(CC) $(CFLAGS) $^ -o $@ -lrt + + +# Clean: delete derived files. +.PHONY: clean +clean: + -$(DEL) ir_spam1 ir_spam1-test.o ir_uart-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o pacer-test.o + + + diff --git a/apps/ir_spam1/doc/Makefile b/apps/ir_spam1/doc/Makefile new file mode 100644 index 0000000..00afecd --- /dev/null +++ b/apps/ir_spam1/doc/Makefile @@ -0,0 +1,45 @@ +# File: Makefile +# Author: M. P. Hayes, UCECE +# Date: 11 Sep 2010 +# Descr: Makefile for ir_uart_test1 docs + +# The scripts used to make the graphs require the program dot; this +# is part of the graphviz package. + +DEL = rm + +all: file_dependencies.pdf module_dependencies.pdf makefile_dependencies.pdf build_dependencies.pdf callgraph.pdf + +file_dependencies.pdf: files.d + ../../../etc/graphdeps.py $< --out $@ + +module_dependencies.pdf: modules.d + ../../../etc/graphdeps.py $< --modules --rotate --out $@ + +makefile_dependencies.pdf: ../Makefile + ../../../etc/graphdeps.py $< --out $@ + +build_dependencies.pdf: ../Makefile + ../../../etc/graphdeps.py $< --out $@ --showops + +callgraph.pdf: callgraph.d + ../../../etc/graphdeps.py --calls --modules $< --out $@ --showops + + +files.d: ../Makefile + (cd ..; ../../etc/makemake.py --relpath --files . . ../../drivers ../../drivers/avr ../../utils ../../extra --exclude system.h > doc/files.d) + + +modules.d: ../Makefile + (cd ..; ../../etc/makemake.py --relpath --modules . . ../../drivers ../../drivers/avr ../../utils ../../extra --exclude system > doc/modules.d) + + +callgraph.d: ../Makefile + (cd ..; ../../etc/makemake.py --cc="avr-gcc" --cflags="-Os -mmcu=atmega32u2" --relpath --calls . . ../../drivers ../../drivers/avr ../../utils ../../extra --exclude system.h > doc/callgraph.d) + + +# Clean: delete derived files. +.PHONY: clean +clean: + -$(DEL) *.d *.pdf + diff --git a/apps/ir_spam1/doc/README b/apps/ir_spam1/doc/README new file mode 100644 index 0000000..39a9712 --- /dev/null +++ b/apps/ir_spam1/doc/README @@ -0,0 +1,16 @@ +Running make in this directory will generate a number of PDF graphs. +In the callgraph, the arrows means "calls". In the dependency graphs, +the arrows means "requires" (or "depends upon"). + +callgraph.pdf This shows the callgraph, i.e., what functions each + function in the program calls. +module_dependencies.pdf This shows the dependencies between the modules. +file_dependencies.pdf This shows the dependencies between the files. +makefile_dependencies.pdf This shows the dependencies required by make when + building the program. +build_dependencies.pdf This is like makefile_dependencies.pdf but shows + the operations performed to generate the new file. + +callgraph.d This shows the callgraph in text format. +files.d This shows the file dependencies in text format. +modules.d This shows the module dependencies in text format. diff --git a/apps/ir_spam1/ir_spam1.c b/apps/ir_spam1/ir_spam1.c new file mode 100644 index 0000000..f61f497 --- /dev/null +++ b/apps/ir_spam1/ir_spam1.c @@ -0,0 +1,35 @@ +/** @file ir_spam1.c + @author M. P. Hayes, UCECE + @date 24 September 2013 + @brief Repeatedly send message over IR. +*/ + +#include "system.h" +#include "pacer.h" +#include "ir_uart.h" + +/* Define polling rate in Hz. */ +#define LOOP_RATE 20 + + +int main (void) +{ + int count = 5; + + system_init (); + + ir_uart_init (); + + pacer_init (LOOP_RATE); + + /* Paced loop. */ + while (1) + { + /* Wait for next tick. */ + pacer_wait (); + + ir_uart_putc ('A'); + } + + return 0; +} diff --git a/apps/pacerdemo1/Makefile.test b/apps/pacerdemo1/Makefile.test new file mode 100644 index 0000000..0e6e90b --- /dev/null +++ b/apps/pacerdemo1/Makefile.test @@ -0,0 +1,52 @@ +# File: Makefile +# Author: M. P. Hayes, UCECE +# Date: 11 Sep 2010 +# Descr: Makefile for pacerdemo1 + +CC = gcc +CFLAGS = -Wall -Wstrict-prototypes -Wextra -g -I../../drivers/test -I../../drivers -I../../utils + +DEL = rm + + +# Default target. +all: pacerdemo1 + + +# Compile: create object files from C source files. +pacerdemo1-test.o: pacerdemo1.c ../../drivers/led.h ../../drivers/test/avrtest.h ../../drivers/test/pio.h ../../drivers/test/system.h ../../utils/pacer.h + $(CC) -c $(CFLAGS) $< -o $@ + +led-test.o: ../../drivers/led.c ../../drivers/led.h ../../drivers/test/avrtest.h ../../drivers/test/pio.h ../../drivers/test/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +mgetkey-test.o: ../../drivers/test/mgetkey.c ../../drivers/test/mgetkey.h + $(CC) -c $(CFLAGS) $< -o $@ + +pio-test.o: ../../drivers/test/pio.c ../../drivers/test/avrtest.h ../../drivers/test/pio.h ../../drivers/test/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +system-test.o: ../../drivers/test/system.c ../../drivers/test/avrtest.h ../../drivers/test/mgetkey.h ../../drivers/test/pio.h ../../drivers/test/system.h + $(CC) -c $(CFLAGS) $< -o $@ + +timer-test.o: ../../drivers/test/timer.c ../../drivers/test/system.h ../../drivers/test/timer.h + $(CC) -c $(CFLAGS) $< -o $@ + +pacer-test.o: ../../utils/pacer.c ../../drivers/test/system.h ../../drivers/test/timer.h ../../utils/pacer.h + $(CC) -c $(CFLAGS) $< -o $@ + + + + +# Link: create executable file from object files. +pacerdemo1: pacerdemo1-test.o led-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o pacer-test.o + $(CC) $(CFLAGS) $^ -o $@ -lrt + + +# Clean: delete derived files. +.PHONY: clean +clean: + -$(DEL) pacerdemo1 pacerdemo1-test.o led-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o pacer-test.o + + + diff --git a/drivers/avr/system.c b/drivers/avr/system.c index f7b30af..f494d96 100644 --- a/drivers/avr/system.c +++ b/drivers/avr/system.c @@ -30,6 +30,7 @@ static void system_watchdog_timer_init (void) } +/** Initialise clock and disable watchdog timer. */ void system_init (void) { system_clock_init (); diff --git a/drivers/avr/system.h b/drivers/avr/system.h index f2e2e92..670542e 100644 --- a/drivers/avr/system.h +++ b/drivers/avr/system.h @@ -12,7 +12,7 @@ typedef uint8_t bool; -/* Useful macros. */ +/** Useful macros. */ #define BIT(X) (1 << (X)) #define ARRAY_SIZE(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) @@ -20,11 +20,11 @@ typedef uint8_t bool; #define __unused__ __attribute__ ((unused)) -/* Clock frequency Hz. */ +/** Clock frequency Hz. */ #define F_CPU 8000000 -/* LED matrix columns. (Note these are labelled in reverse order on +/** LED matrix columns. (Note these are labelled in reverse order on the schematic.) */ #define LEDMAT_COL1_PIO PC6_PIO #define LEDMAT_COL2_PIO PB7_PIO @@ -34,7 +34,7 @@ typedef uint8_t bool; #define LEDMAT_COLS_NUM 5 -/* LED matrix rows. */ +/** LED matrix rows. */ #define LEDMAT_ROW1_PIO PB6_PIO #define LEDMAT_ROW2_PIO PB5_PIO #define LEDMAT_ROW3_PIO PB4_PIO @@ -45,12 +45,12 @@ typedef uint8_t bool; #define LEDMAT_ROWS_NUM 7 -/* Button. */ +/** Button. */ #define BUTTON1 0 #define BUTTON1_PIO PD7_PIO -/* Navswitch. */ +/** Navswitch. */ #define NAVSWITCH_PUSH_PIO LEDMAT_COL3_PIO #define NAVSWITCH_DOWN_PIO NAVSWITCH_PUSH_PIO #define NAVSWITCH_EAST_PIO LEDMAT_COL1_PIO @@ -59,18 +59,19 @@ typedef uint8_t bool; #define NAVSWITCH_SOUTH_PIO LEDMAT_COL5_PIO -/* LED (active high). */ +/** LED (active high). */ #define LED1 0 #define LED1_PIO PC2_PIO -/* Infrared transmitter LED and receiver. */ +/** Infrared transmitter LED and receiver. */ #define IR_TX_LOW_PIO PD3_PIO #define IR_TX_HIGH_PIO PD0_PIO #define IR_RX_PIO PD2_PIO #define IR_MODULATION_FREQ 36e3 +/** Initialise clock and disable watchdog timer. */ void system_init (void); #endif diff --git a/drivers/ir_rx5_rx.c b/drivers/ir_rx5_rx.c new file mode 100644 index 0000000..0d8fab3 --- /dev/null +++ b/drivers/ir_rx5_rx.c @@ -0,0 +1,151 @@ +/** @file ir_rc5_rx.c + @author M. P. Hayes, UCECE + @date 21 May 2013 + @brief Infrared serial receiver driver for Phillips RC5 protocol. +*/ + +/* The Phillips RC-5 protocol uses the following format of 14 bits: + 1 start bit + 1 field bit (this used to be a second start bit) + 1 toggle bit + 5 address bits + 6 command bits + + Manchester encoding is used for the bits. The start bit is a `1' bits. + `1' bits have the IR modulation on for the second half of the cycle. + `0' bits have the IR modulation on for the first half of the cycle. + + Each bit period is 1778 microseconds (64 cycles of 36 kHz modulation) + thus a frame is 24.9 ms. + + While a button is pressed, a frame is repeatedly sent. If the button + is repressed, the toggle bit is changed. + + This is a simple polled implementation that will block for the entire frame + if it detects a start bit. +*/ + + +#include "ir_rc5_rx.h" +#include "pio.h" +#include "delay.h" + +#define IR_RC5_BIT_PERIOD_US 1778 + +#ifndef IR_RC5_RX_ACTIVE_STATE +/* Most IR demodulators have an active low output. */ +#define IR_RC5_RX_ACTIVE_STATE 0 +#endif + + +/** Return output state of IR receiver. + @return IR receiver state (1 = IR modulation detected). */ +static inline uint8_t ir_rc5_rx_get (void) +{ + return pio_input_get (IR_RC5_RX_PIO) == IR_RC5_RX_ACTIVE_STATE; +} + + +uint8_t ir_rc5_rx_ready_p (void) +{ + return ir_rc5_rx_get (); +} + + +static uint16_t ir_rc5_rx_wait_state (uint8_t state) +{ + uint16_t us; + + for (us = 0; us < IR_RC5_BIT_PERIOD_US; us++) + { + if (ir_rc5_rx_get () == state) + return us; + /* TODO: figure out how to determine the fudge term. Ideally, + we should poll a counter incremented by the CPU clock. */ + DELAY_US (1 - 0.4); + } + return us; +} + + +static uint16_t ir_rc5_rx_wait_transition (void) +{ + uint8_t initial; + + initial = ir_rc5_rx_get (); + + return ir_rc5_rx_wait_state (!initial); +} + + +/** Receive RC5 data packet over IR serial link. + @return 14-bits of data or error status code + @note No error checking is performed. If there is no activity on the + IR serial link, this function returns immediately. Otherwise, this + function blocks until the entire frame is received. This must be called + frequently to ensure that a start bit is seen. */ +int16_t ir_rc5_rx_read (void) +{ + int16_t data; + int i; + uint16_t us; + + /* Look to see if there is some IR modulation marking the second + half of the first start bit. It is possible that we may have + missed the start bit. In this case we are likely to + time out. */ + if (!ir_rc5_rx_ready_p ()) + return IR_RC5_RX_NONE; + + /* The old RC-5 format had two start bits; this made a bit-bashed + software implementation easier. The problem is that we have + been called just before the falling edge of the start bit. + So we have to special case these two bits. */ + + /* Search for the next falling transition. */ + us = ir_rc5_rx_wait_state (0); + if (us >= IR_RC5_BIT_PERIOD_US) + return IR_RC5_RX_TIMEOUT; + + if (us > (IR_RC5_BIT_PERIOD_US >> 1)) + { + /* The field bit is 0. */ + data = 2; + } + else + { + /* The field bit is 1; so delay until middle of bit period. */ + data = 3; + us = ir_rc5_rx_wait_state (1); + if (us >= IR_RC5_BIT_PERIOD_US) + return IR_RC5_RX_TIMEOUT; + } + + for (i = 2; i < 14; i++) + { + data <<= 1; + + DELAY_US (0.5 * IR_RC5_BIT_PERIOD_US + 100); + + us = ir_rc5_rx_wait_transition (); + if (us >= IR_RC5_BIT_PERIOD_US) + return IR_RC5_RX_TIMEOUT; + + if (ir_rc5_rx_get ()) + data |= 1; + } + + return data; +} + + +/** Initialise IR serial receiver driver. */ +void ir_rc5_rx_init (void) +{ + /* Ensure PIO clock activated for reading. */ + pio_init (IR_RX_PIO); + + /* Configure IR receiver PIO as input. */ + pio_config_set (IR_RX_PIO, PIO_INPUT); +} + diff --git a/drivers/ir_rx5_rx.h b/drivers/ir_rx5_rx.h new file mode 100644 index 0000000..803aa6d --- /dev/null +++ b/drivers/ir_rx5_rx.h @@ -0,0 +1,34 @@ +/** @file ir_rc5_rx.h + @author M. P. Hayes, UCECE + @date 21 May 2013 + @brief Infrared serial receiver driver for Phillips RC5 protocol. +*/ + +#ifndef IR_RC5_RX_H +#define IR_RC5_RX_H + +#include "config.h" + +/** Status return codes. */ +typedef enum ir_rc5_rx_ret +{ + /** No data to read. */ + IR_RC5_RX_NONE = 0, + /** Timeout waiting for transition. */ + IR_RC5_RX_TIMEOUT = -1 +} ir_rc5_rx_ret_t; + + +/** Receive RC5 data packet over IR serial link. + @return 14-bits of data or error status code + @note No error checking is performed. If there is no activity on the + IR serial link, this function returns immediately. Otherwise, this + function blocks until the entire frame is received. This must be called + frequently to ensure that a start bit is seen. */ +int16_t ir_rc5_rx_read (void); + + +/** Initialise IR serial receiver driver. */ +void ir_rc5_rx_init (void); + +#endif