Generate callgraph

This commit is contained in:
Michael Hayes
2011-08-27 01:46:08 +00:00
commit 513810e138
233 changed files with 22993 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
#ifndef AVRTEST_H
#define AVRTEST_H
#include "system.h"
typedef struct SFR
{
uint8_t PORTB;
uint8_t DDRB;
uint8_t PINB;
uint8_t PORTC;
uint8_t DDRC;
uint8_t PINC;
uint8_t PORTD;
uint8_t DDRD;
uint8_t PIND;
} SFR_t;
#define PORTB SFR.PORTB
#define PORTC SFR.PORTC
#define PORTD SFR.PORTD
#define DDRB SFR.DDRB
#define DDRC SFR.DDRC
#define DDRD SFR.DDRD
#define PINB SFR.PINB
#define PINC SFR.PINC
#define PIND SFR.PINC
extern SFR_t SFR;
#endif
+1
View File
@@ -0,0 +1 @@
#define DELAY_US(US)
+85
View File
@@ -0,0 +1,85 @@
/** @file eeprom.c
@author M. P. Hayes, UCECE
@date 15 May 2007
@brief
*/
#include "system.h"
#include "eeprom.h"
#include <stdio.h>
#include <string.h>
#define EEPROM_SIZE 512
#define EEPROM_FILENAME "ucfk_eeprom.dat"
static void
eeprom_file_write (void *buffer, eeprom_size_t size)
{
FILE *fp;
fp = fopen (EEPROM_FILENAME, "w");
if (fp)
{
fwrite (buffer, size, 1, fp);
fclose (fp);
}
}
static void
eeprom_file_read (void *buffer, eeprom_size_t size)
{
FILE *fp;
fp = fopen (EEPROM_FILENAME, "r");
if (!fp)
{
/* If file not present assume EEPROM is erased and thus
contains the values 0xff. */
memset (buffer, 0xff, size);
eeprom_file_write (buffer, size);
}
else
{
fread (buffer, size, 1, fp);
fclose (fp);
}
}
/* Read SIZE bytes from ADDR into BUFFER. */
eeprom_size_t
eeprom_read (eeprom_addr_t addr, void *buffer, eeprom_size_t size)
{
eeprom_size_t i;
uint8_t *data = buffer;
uint8_t eeprom[EEPROM_SIZE];
eeprom_file_read (eeprom, EEPROM_SIZE);
for (i = 0; i < size && addr < EEPROM_SIZE; i++)
data[i] = eeprom[addr++];
return i;
}
/* Write SIZE bytes to ADDR from BUFFER. */
eeprom_size_t
eeprom_write (eeprom_addr_t addr, const void *buffer, eeprom_size_t size)
{
eeprom_size_t i;
const uint8_t *data = buffer;
uint8_t eeprom[EEPROM_SIZE];
eeprom_file_read (eeprom, EEPROM_SIZE);
for (i = 0; i < size && addr < EEPROM_SIZE; i++)
eeprom[addr++] = data[i];
eeprom_file_write (eeprom, EEPROM_SIZE);
return i;
}
+30
View File
@@ -0,0 +1,30 @@
/** @file eeprom.h
@author Michael Hayes
@date 13 Nov 2006
@brief Routines to read/write internal EEPROM.
@defgroup eeprom EEPROM driver
This module implements a driver to read/write the EEPROM of an
ATmega microcontroller. The EEPROM is useful for storing
persistent data when the power is removed.
*/
#ifndef EEPROM_H
#define EEPROM_H
#include "system.h"
typedef uint16_t eeprom_addr_t;
typedef uint16_t eeprom_size_t;
/* Read SIZE bytes from ADDR into BUFFER. */
extern eeprom_size_t
eeprom_read (eeprom_addr_t addr, void *buffer, eeprom_size_t size);
/* Write SIZE bytes to ADDR from BUFFER. */
extern eeprom_size_t
eeprom_write (eeprom_addr_t addr, const void *buffer, eeprom_size_t size);
#endif
+64
View File
@@ -0,0 +1,64 @@
/** @file ir_uart.c
@author M. P. Hayes, UCECE
@date 1 Aug 2011
@brief This is just a stub that does nothing.
*/
#include "system.h"
#include "ir_uart.h"
/* Return non-zero if there is a character ready to be read. */
bool
ir_uart_read_ready_p (void)
{
return 0;
}
/* Read character from IR_UART. This blocks if nothing
is available to read. */
int8_t
ir_uart_getc (void)
{
return 0;
}
/* Return non-zero if a character can be written without blocking. */
bool
ir_uart_write_ready_p (void)
{
return 0;
}
/* Return non-zero if transmitter finished. */
bool
ir_uart_write_finished_p (void)
{
return 1;
}
/* Write character to IR_UART. This returns zero if
the character could not be written. */
int8_t
ir_uart_putc (__unused__ char ch)
{
return 0;
}
/* Write string to IR_UART. */
void
ir_uart_puts (__unused__ const char *str)
{
}
/* Initialise ir_uart and set baud rate. */
uint8_t
ir_uart_init (void)
{
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
/** @file ir_uart.h
@author Michael Hayes
@date 10 December 2004
*/
#ifndef IR_UART_H
#define IR_UART_H
#include "system.h"
#ifndef IR_UART_BAUD_RATE
#define IR_UART_BAUD_RATE 2400
#endif
/* Return non-zero if there is a character ready to be read. */
bool
ir_uart_read_ready_p (void);
/* Read character from IR_UART. This blocks if nothing
is available to read. */
int8_t
ir_uart_getc (void);
/* Return non-zero if a character can be written without blocking. */
bool
ir_uart_write_ready_p (void);
/* Return non-zero if transmitter finished. */
bool
ir_uart_write_finished_p (void);
/* Write character to IR_UART. This returns zero if
the character could not be written. */
int8_t
ir_uart_putc (char ch);
/* Write string to IR_UART. */
void
ir_uart_puts (const char *str);
/* Initialise ir_uart and set baud rate. */
uint8_t
ir_uart_init (void);
#endif
+94
View File
@@ -0,0 +1,94 @@
/** @file mgetkey.c
@author M. P. Hayes, UCECE
@date 17 July 2011
@brief Non-blocking raw keyboard reading.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include "mgetkey.h"
static struct termios tty_attr_save;
static int tty_init = 0;
/* Get the terminal attributes. */
static int mgetkey_attr_get (struct termios *ptty_attr)
{
if (tcgetattr (STDIN_FILENO, ptty_attr) == -1)
{
perror ("mgetkey: Cannot get tty attributes");
return 0;
}
return 1;
}
/* Set terminal attributes ensuring that the original attributes are
saved. */
static int mgetkey_attr_set (struct termios *ptty_attr)
{
if (tcsetattr (STDIN_FILENO, TCSANOW, ptty_attr) == -1)
{
perror ("mgetkey: Cannot set tty attributes");
return 0;
}
return 1;
}
int mgetkey_init (void)
{
struct termios tty_attr;
if (!tty_init)
{
if (!mgetkey_attr_get (&tty_attr_save))
return 0;
/* Restore terminal attributes on exit. */
atexit (mgetkey_reset);
tty_init = 1;
}
/* Get terminal attributes. */
if (!mgetkey_attr_get (&tty_attr))
return 0;
tty_attr.c_lflag &= ~ECHO; /* No echo. */
tty_attr.c_lflag &= ~ICANON; /* No canonical processing. */
tty_attr.c_cc[VMIN] = 0; /* Don't block. */
tty_attr.c_cc[VTIME] = 0; /* Don't block. */
/* Set terminal attributes. */
return mgetkey_attr_set (&tty_attr);
}
/* Restore the terminal attributes. */
void mgetkey_reset (void)
{
mgetkey_attr_set (&tty_attr_save);
}
/* Read a single key stroke from the keyboard. This blocks until
a key is typed. Note that the key is not echoed. */
int mgetkey (void)
{
int key;
if (!tty_init)
mgetkey_init ();
key = getchar ();
if (key == -1)
key = 0;
return key;
}
+19
View File
@@ -0,0 +1,19 @@
/** @file mgetkey.h
@author M. P. Hayes, UCECE
@date 17 July 2011
@brief Non-blocking raw keyboard reading.
*/
#ifndef MGETKEY_H
#define MGETKEY_H
/* Read a single key stroke from the keyboard. If no key has been
pressed then zero is returned. Note that the key is not
echoed. */
int mgetkey (void);
/* Restore terminal settings. */
void mgetkey_reset (void);
#endif
+7
View File
@@ -0,0 +1,7 @@
/** @file pio.c
@author M. P. Hayes, UCECE
@date 11 Jan 2006
@brief PIO hardware abstraction for AVR microcontroller.
@note This implementation is empty; inline functions are used
in pio.h instead for performance.
*/
+265
View File
@@ -0,0 +1,265 @@
/** @file pio.h
@author M. P. Hayes, UCECE
@date 11 Jan 2006
@brief PIO hardware abstraction for AVR microcontroller.
@note Macros and inline functions are used to avoid function
call overhead and to allow compile-time constant folding.
@defgroup pio PIO driver
This module implements a driver for general purpose I/O ports.
Its purpose is to provide a microcontroller independent
abstraction of a PIO pin. Here's an example:
@code
#include "pio.h"
#define LED_PIO PIO_DEFINE (PORT_B, 5)
void main (void)
{
system_init ();
pio_config_set (LED_PIO, PIO_OUTPUT_LOW);
pio_output_high (LED_PIO);
while (1);
}
@endcode
In this example, when port B5 is configured as an output it is set
low.
*/
#ifndef PIO_H
#define PIO_H
#include "system.h"
#include "avrtest.h"
/** Define port names, note not all the ports are available on some AVRs. */
#ifdef PORTA
#define PORT_A &PORTA
#endif
#ifdef PORTB
#define PORT_B &PORTB
#endif
#ifdef PORTC
#define PORT_C &PORTC
#endif
#ifdef PORTD
#define PORT_D &PORTD
#endif
#ifdef PORTE
#define PORT_E &PORTE
#endif
#ifdef PORTF
#define PORT_F &PORTF
#endif
#ifdef PORTG
#define PORT_G &PORTG
#endif
typedef volatile uint8_t *pio_port_t;
typedef uint8_t pio_mask_t;
typedef struct
{
pio_port_t port;
pio_mask_t bitmask;
} pio_t;
/** Define PIO pin types. The two flavours of PIO_OUTPUT are to
ensure the port is configured without glitching due to the time
taken before calling pio_output_set. */
typedef enum pio_config_enum
{
PIO_INPUT = 1, /** Configure as input pin. */
PIO_PULLUP, /** Configure as input pin with pullup. */
PIO_OUTPUT_LOW, /** Configure as output, initially low. */
PIO_OUTPUT_HIGH, /** Configure as output, initially high. */
} pio_config_t;
/** DDR PORT Comment
0 0 High impedance input
0 1 Weak pullup input
1 0 Output low
1 1 Output high
*/
/** Define a PIO as a compound literal structure in terms of a port and
a bitmask. */
#define PIO_DEFINE(PORT, PORTBIT) (pio_t){.port = PORT, .bitmask = BIT (PORTBIT)}
/** Private macro to lookup bitmask. */
#define PIO_BITMASK_(pio) (pio.bitmask)
/** Private macro to lookup port register. */
#define PIO_PORT_(pio) (pio.port)
/** Private macro to map a pio to its corresponding data direction
register (DDR). NB, the DDR and PORT registers must be separated
by the same number of bytes in all cases. PORTB is used for the
pattern since PORTA is not always defined for some AVRs. */
#define PIO_DDR_(pio) (*(PIO_PORT_ (pio) + (&DDRB - &PORTB)))
/** Private macro to map a pio to its input register (PIN). NB, the
PIN and PORT registers must be separated by the same number of
bytes in all cases. PORTB is used for the pattern since PORTA is
not always defined for some AVRs. */
#define PIO_PIN_(pio) (*(PIO_PORT_ (pio) + (&PINB - &PORTB)))
/** Private macro to access a pio data register. */
#define PIO_DATA_(pio) (*PIO_PORT_ (pio))
/** Configure pio.
@param pio PIO to configure
@param config PIO configuration type
@return non-zero for success. */
static inline
bool pio_config_set (pio_t pio, pio_config_t config)
{
switch (config)
{
case PIO_OUTPUT_LOW:
PIO_DATA_ (pio) &= ~PIO_BITMASK_ (pio);
PIO_DDR_ (pio) |= PIO_BITMASK_ (pio);
return 1;
case PIO_OUTPUT_HIGH:
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
PIO_DDR_ (pio) |= PIO_BITMASK_ (pio);
return 1;
case PIO_INPUT:
PIO_DDR_ (pio) &= ~PIO_BITMASK_ (pio);
PIO_DATA_ (pio) &= ~PIO_BITMASK_ (pio);
return 1;
case PIO_PULLUP:
PIO_DDR_ (pio) &= ~PIO_BITMASK_ (pio);
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
return 1;
default:
return 0;
}
}
/** Return pio configuration
@param pio
@return config */
static inline
pio_config_t pio_config_get (pio_t pio)
{
bool ddr;
bool port;
ddr = PIO_DDR_ (pio) & PIO_BITMASK_ (pio);
port = PIO_DATA_ (pio) & PIO_BITMASK_ (pio);
if (ddr)
{
if (port)
return PIO_OUTPUT_HIGH;
else
return PIO_OUTPUT_LOW;
}
if (port)
return PIO_PULLUP;
return PIO_INPUT;
}
/** Set pio high.
@param pio */
static inline
void pio_output_high (pio_t pio)
{
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
}
/** Set pio low.
@param pio */
static inline
void pio_output_low (pio_t pio)
{
PIO_DATA_ (pio) &= ~PIO_BITMASK_ (pio);
}
/** Toggle pio.
@param pio */
static inline
void pio_output_toggle (pio_t pio)
{
PIO_DATA_ (pio) ^= PIO_BITMASK_ (pio);
}
/** Read input state from pio.
@param pio
@return input state of pio */
static inline
bool pio_input_get (pio_t pio)
{
return (PIO_PIN_ (pio) & PIO_BITMASK_ (pio)) != 0;
}
/** Get output state of pio.
@param pio
@return output state of pio */
static inline
bool pio_output_get (pio_t pio)
{
return (PIO_DATA_ (pio) & PIO_BITMASK_ (pio)) != 0;
}
/** Set pio to desired state.
@param pio
@param state value to write pio */
static inline
void pio_output_set (pio_t pio, bool state)
{
state ? pio_output_high (pio) : pio_output_low (pio);
}
/** Set input state for pio (this is only for use by the test scaffold).
@param pio
@param state value for pio input */
static inline
void pio_input_set (pio_t pio, bool state)
{
if (state)
PIO_PIN_ (pio) |= PIO_BITMASK_ (pio);
else
PIO_PIN_ (pio) &= ~PIO_BITMASK_ (pio);
}
#endif
+402
View File
@@ -0,0 +1,402 @@
/** @file system.c
@author M. P. Hayes, UCECE
@date 15 May 2007
@brief Test scaffold for UCFK4.
*/
#include "system.h"
#include "avrtest.h"
#include "pio.h"
#include "mgetkey.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
/** This needs to be at least 50 * 5 for a refresh rate of 50 Hz. */
#define SYSTEM_UPDATE_RATE 400
#define SYSTEM_KEYBOARD_RELEASE_PERIOD 0.2
#define SYSTEM_DISPLAY_PERSISTENCE_PERIOD 0.01
SFR_t SFR = {0, 0, ~0, 0, 0, ~0, 0, 0, ~0};
/* Define PIO pins driving LED matrix rows and columns. */
static const pio_t ledmat_rows[] =
{
LEDMAT_ROW1_PIO,
LEDMAT_ROW2_PIO,
LEDMAT_ROW3_PIO,
LEDMAT_ROW4_PIO,
LEDMAT_ROW5_PIO,
LEDMAT_ROW6_PIO,
LEDMAT_ROW7_PIO
};
static const pio_t ledmat_cols[] =
{
LEDMAT_COL1_PIO,
LEDMAT_COL2_PIO,
LEDMAT_COL3_PIO,
LEDMAT_COL4_PIO,
LEDMAT_COL5_PIO
};
typedef enum {NAVSWITCH_NONE, NAVSWITCH_EAST, NAVSWITCH_SOUTH,
NAVSWITCH_WEST, NAVSWITCH_NORTH, NAVSWITCH_PUSH} system_navswitch_t;
typedef enum {BUTTON_NONE, BUTTON_1} system_button_t;
static void system_display_update (void)
{
int row;
int col;
/* Persistence time (s). */
double tau = SYSTEM_DISPLAY_PERSISTENCE_PERIOD;
/* Sample period (s). */
double delta_t;
/* Exponential filter parameter. */
double alpha;
static uint8_t tdisplay[LEDMAT_ROWS_NUM][LEDMAT_COLS_NUM];
delta_t = 1.0 / SYSTEM_UPDATE_RATE;
alpha = tau / (tau + delta_t);
for (row = 0; row < LEDMAT_ROWS_NUM; row++)
{
for (col = 0; col < LEDMAT_COLS_NUM; col++)
{
uint8_t on;
/* Determine if pixel is on. */
on = !pio_output_get (ledmat_rows[row])
&& !pio_output_get (ledmat_cols[col]);
/* Apply exponential filter to provide some persistence.
This has an impulse response of exp(-t / tau) u(t). */
tdisplay[row][col] = tdisplay[row][col] * alpha + (1 - alpha) * 100 * on;
printf ("%c", tdisplay[row][col] > 1 ? '@' : '.');
}
printf ("\n");
}
printf ("\n");
/* Move cursor up. */
printf ("\e[%dA", LEDMAT_ROWS_NUM + 1);
}
static void system_navswitch_set (system_navswitch_t navswitch, bool state)
{
switch (navswitch)
{
case NAVSWITCH_NONE:
break;
case NAVSWITCH_NORTH:
pio_input_set (NAVSWITCH_NORTH_PIO, !state);
break;
case NAVSWITCH_EAST:
pio_input_set (NAVSWITCH_EAST_PIO, !state);
break;
case NAVSWITCH_SOUTH:
pio_input_set (NAVSWITCH_SOUTH_PIO, !state);
break;
case NAVSWITCH_WEST:
pio_input_set (NAVSWITCH_WEST_PIO, !state);
break;
case NAVSWITCH_PUSH:
pio_input_set (NAVSWITCH_PUSH_PIO, !state);
break;
}
}
static void system_navswitch_press (system_navswitch_t navswitch)
{
system_navswitch_set (navswitch, 1);
}
static void system_navswitch_release (system_navswitch_t navswitch)
{
system_navswitch_set (navswitch, 0);
}
static void system_navswitch_select (system_navswitch_t navswitch)
{
static system_navswitch_t last = NAVSWITCH_NONE;
static int counter;
if (navswitch == NAVSWITCH_NONE)
{
if (counter)
{
counter--;
if (!counter)
{
system_navswitch_release (last);
last = NAVSWITCH_NONE;
}
}
return;
}
counter = SYSTEM_UPDATE_RATE * SYSTEM_KEYBOARD_RELEASE_PERIOD;
if (last == navswitch)
return;
system_navswitch_release (last);
last = navswitch;
system_navswitch_press (navswitch);
}
static void system_button_set (system_button_t button, bool state)
{
switch (button)
{
case BUTTON_NONE:
break;
case BUTTON_1:
/* Active high. */
pio_input_set (BUTTON1_PIO, state);
break;
}
}
static void system_button_press (system_button_t button)
{
system_button_set (button, 1);
}
static void system_button_release (system_button_t button)
{
system_button_set (button, 0);
}
static void system_button_select (system_button_t button)
{
static system_button_t last = BUTTON_NONE;
static int counter;
if (button == BUTTON_NONE)
{
if (counter)
{
counter--;
if (!counter)
{
system_button_release (last);
last = BUTTON_NONE;
}
}
return;
}
counter = SYSTEM_UPDATE_RATE * SYSTEM_KEYBOARD_RELEASE_PERIOD;
if (last == button)
return;
system_button_release (last);
last = button;
system_button_press (button);
}
static void system_keyboard_init (void)
{
system_navswitch_release (NAVSWITCH_PUSH);
system_navswitch_release (NAVSWITCH_NORTH);
system_navswitch_release (NAVSWITCH_EAST);
system_navswitch_release (NAVSWITCH_SOUTH);
system_navswitch_release (NAVSWITCH_WEST);
system_button_release (BUTTON_1);
}
static void system_keyboard_update (void)
{
static int state = 0;
int key;
system_navswitch_select (NAVSWITCH_NONE);
system_button_select (BUTTON_NONE);
key = mgetkey ();
switch (state)
{
case 0:
switch (key)
{
case '\e':
/* Have escape character. */
state = 1;
break;
case ' ':
system_navswitch_select (NAVSWITCH_PUSH);
break;
case '.':
system_button_select (BUTTON_1);
break;
default:
break;
}
break;
case 1:
if (key == '[')
state = 2;
else
state = 0;
break;
case 2:
state = 0;
switch (key)
{
case 'A':
system_navswitch_select (NAVSWITCH_NORTH);
break;
case 'B':
system_navswitch_select (NAVSWITCH_SOUTH);
break;
case 'C':
system_navswitch_select (NAVSWITCH_EAST);
break;
case 'D':
system_navswitch_select (NAVSWITCH_WEST);
break;
default:
break;
}
break;
}
}
static void system_update (void)
{
system_display_update ();
system_keyboard_update ();
}
static void
system_handler (__unused__ int sig, __unused__ siginfo_t *si,
__unused__ void *uc)
{
system_update ();
}
typedef void (*sighandler_t)(int, siginfo_t *, void *);
static int system_interrupt_init (sighandler_t handler, int rate)
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
long long period_ns;
sigset_t mask;
struct sigaction sa;
static int signum = 0;
/* When debugging with gdb use "handle SIG34 noprint". */
if (!signum)
signum = SIGRTMIN;
/* Establish handler for timer signal. */
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset (&sa.sa_mask);
if (sigaction (signum, &sa, NULL) == -1)
{
perror ("sigaction");
exit (EXIT_FAILURE);
}
/* Block timer signal temporarily. */
sigemptyset (&mask);
sigaddset (&mask, signum);
if (sigprocmask (SIG_SETMASK, &mask, NULL) == -1)
{
perror ("sigprocmask");
exit (EXIT_FAILURE);
}
/* Create the timer. */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = signum;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create (CLOCK_REALTIME, &sev, &timerid) == -1)
{
perror ("timer_create");
exit (EXIT_FAILURE);
}
/* Start the timer */
period_ns = 1000000000 / rate;
its.it_value.tv_sec = period_ns / 1000000000;
its.it_value.tv_nsec = period_ns % 1000000000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (timer_settime (timerid, 0, &its, NULL) == -1)
{
perror ("timer_settime");
exit (EXIT_FAILURE);
}
/* Unlock the timer signal, so that timer notification
can be delivered. */
if (sigprocmask (SIG_UNBLOCK, &mask, NULL) == -1)
{
perror ("sigprocmask");
exit (EXIT_FAILURE);
}
signum++;
return signum;
}
void system_init (void)
{
system_keyboard_init ();
system_interrupt_init (system_handler, SYSTEM_UPDATE_RATE);
}
+74
View File
@@ -0,0 +1,74 @@
/** @file system.h
@author M. P. Hayes, UCECE
@date 15 May 2007
@brief System specific definitions
*/
#ifndef SYSTEM_H
#define SYSTEM_H
/* Data typedefs. */
#include <stdint.h>
typedef uint8_t bool;
/* Useful macros. */
#define BIT(X) (1 << (X))
#define ARRAY_SIZE(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0]))
#define __unused__ __attribute__ ((unused))
/* Clock frequency Hz. */
#define F_CPU 8000000
/* LED matrix columns. */
#define LEDMAT_COL1_PIO PIO_DEFINE(PORT_C, 6)
#define LEDMAT_COL2_PIO PIO_DEFINE(PORT_B, 7)
#define LEDMAT_COL3_PIO PIO_DEFINE(PORT_C, 4)
#define LEDMAT_COL4_PIO PIO_DEFINE(PORT_C, 7)
#define LEDMAT_COL5_PIO PIO_DEFINE(PORT_C, 5)
#define LEDMAT_COLS_NUM 5
/* LED matrix rows. */
#define LEDMAT_ROW1_PIO PIO_DEFINE(PORT_B, 6)
#define LEDMAT_ROW2_PIO PIO_DEFINE(PORT_B, 5)
#define LEDMAT_ROW3_PIO PIO_DEFINE(PORT_B, 4)
#define LEDMAT_ROW4_PIO PIO_DEFINE(PORT_B, 3)
#define LEDMAT_ROW5_PIO PIO_DEFINE(PORT_B, 2)
#define LEDMAT_ROW6_PIO PIO_DEFINE(PORT_B, 1)
#define LEDMAT_ROW7_PIO PIO_DEFINE(PORT_B, 0)
#define LEDMAT_ROWS_NUM 7
/* Button. */
#define BUTTON1 0
#define BUTTON1_PIO PIO_DEFINE(PORT_D, 7)
/* Navswitch. */
#define NAVSWITCH_PUSH_PIO LEDMAT_COL3_PIO
#define NAVSWITCH_EAST_PIO LEDMAT_COL1_PIO
#define NAVSWITCH_WEST_PIO LEDMAT_COL2_PIO
#define NAVSWITCH_NORTH_PIO LEDMAT_COL4_PIO
#define NAVSWITCH_SOUTH_PIO LEDMAT_COL5_PIO
/* LED (active high). */
#define LED1 0
#define LED1_PIO PIO_DEFINE(PORT_C, 2)
/* Infrared transmitter LED and receiver. */
#define IR_TX_LOW_PIO PIO_DEFINE(PORT_D, 3)
#define IR_TX_HIGH_PIO PIO_DEFINE(PORT_D, 0)
#define IR_RX_PIO PIO_DEFINE(PORT_D, 2)
#define IR_MODULATION_FREQ 36e3
void system_init (void);
#endif
+57
View File
@@ -0,0 +1,57 @@
/** @file system.h
@author M. P. Hayes, UCECE
@date 15 May 2007
@brief Target specific definitions
*/
#ifndef TARGET_H
#define TARGET_H
#define F_CPU 8000000
/* LED matrix columns. */
#define LEDMAT_COL1_PIO PIO_DEFINE(PORT_C, 5)
#define LEDMAT_COL2_PIO PIO_DEFINE(PORT_C, 7)
#define LEDMAT_COL3_PIO PIO_DEFINE(PORT_C, 4)
#define LEDMAT_COL4_PIO PIO_DEFINE(PORT_B, 7)
#define LEDMAT_COL5_PIO PIO_DEFINE(PORT_C, 6)
#define LEDMAT_COLS_NUM 5
/* LED matrix rows. */
#define LEDMAT_ROW1_PIO PIO_DEFINE(PORT_B, 0)
#define LEDMAT_ROW2_PIO PIO_DEFINE(PORT_B, 1)
#define LEDMAT_ROW3_PIO PIO_DEFINE(PORT_B, 2)
#define LEDMAT_ROW4_PIO PIO_DEFINE(PORT_B, 3)
#define LEDMAT_ROW5_PIO PIO_DEFINE(PORT_B, 4)
#define LEDMAT_ROW6_PIO PIO_DEFINE(PORT_B, 5)
#define LEDMAT_ROW7_PIO PIO_DEFINE(PORT_B, 6)
#define LEDMAT_ROWS_NUM 7
/* Button. */
#define BUTTON1 0
#define BUTTON1_PIO PIO_DEFINE(PORT_D, 7)
/* Navswitch. */
#define NAVSWITCH_PUSH_PIO LEDMAT_COL3_PIO
#define NAVSWITCH_EAST_PIO LEDMAT_COL1_PIO
#define NAVSWITCH_WEST_PIO LEDMAT_COL2_PIO
#define NAVSWITCH_NORTH_PIO LEDMAT_COL4_PIO
#define NAVSWITCH_SOUTH_PIO LEDMAT_COL5_PIO
/* LED (active high). */
#define LED1 0
#define LED1_PIO PIO_DEFINE(PORT_C, 2)
/* Infrared transmitter LED and receiver. */
#define IR_TX_HIGH_PIO PIO_DEFINE(PORT_D, 3)
#define IR_TX_LOW_PIO PIO_DEFINE(PORT_D, 0)
#define IR_RX_PIO PIO_DEFINE(PORT_D, 2)
#define IR_MODULATION_FREQ 36e3
#endif
+72
View File
@@ -0,0 +1,72 @@
/** @file timer.c
@author M. P. Hayes, UCECE
@date 21 August 2007
Description: Support for timer.
*/
#include "timer.h"
#include "unistd.h"
#include "time.h"
#include "system.h"
#include <stdio.h>
static timer_tick_t offset;
/* Initialise timer. */
void timer_init (void)
{
/* Save offset so timer starts around 0. */
offset = timer_get ();
}
/** Get current time:
@return current time in ticks. */
timer_tick_t timer_get (void)
{
struct timespec time;
uint64_t time_us;
uint64_t ticks;
clock_gettime (CLOCK_MONOTONIC, &time);
time_us = time.tv_sec * 1000000 + time.tv_nsec / 1000;
ticks = time_us * TIMER_RATE / 1000000;
return (timer_tick_t) ticks - offset;
}
/** Wait until specified time:
@param when time to sleep until
@return current time. */
timer_tick_t timer_wait_until (timer_tick_t when)
{
while (1)
{
timer_tick_t diff;
timer_tick_t now;
now = timer_get ();
diff = now - when;
/* Allow for 1000 tick overrun. */
if (diff < TIMER_OVERRUN_MAX)
return now;
diff = when - now;
usleep (diff * 1e6 / TIMER_RATE);
}
}
/** Wait for specified period:
@param period how long to wait
@return current time. */
timer_tick_t timer_wait (timer_tick_t period)
{
return timer_wait_until (timer_get () + period);
}
+97
View File
@@ -0,0 +1,97 @@
/** @file timer.h
@author M. P. Hayes, UCECE
@date 18 August 2011
@brief Timer support.
@defgroup timer Timer module
This module provides simple timer support by abstracting a
hardware timer.
The rate that the timer is incremented is specified by the
macro TIMER_CLOCK_DIVISOR in the header file system.h This
must be a value supported by the timer clock prescaler.
The rate that the timer is incremented can be found using the
macro TIMER_RATE.
The timer is free-running and will increment TIMER_RATE times
per second. When the timer reaches 65535 on the next increment
it rolls over to 0.
Here's a simple example for turning an LED on for 0.5 second
and then off for 0.75 second.
@code
#include "timer.h"
#include "led.h"
void main (void)
{
timer_tick_t now;
system_init ();
timer_init ();
led_init ();
now = timer_get ();
while (1)
{
led_set (LED1, 1);
now = timer_wait_until (now + (timer_tick_t)(TIMER_RATE * 0.5));
led_set (LED1, 0);
now = timer_wait_until (now + (timer_tick_t)(TIMER_RATE * 0.75));
}
}
@endcode
*/
#ifndef TIMER_H
#define TIMER_H
#include "system.h"
#ifndef TIMER_CLOCK_DIVISOR
#define TIMER_CLOCK_DIVISOR 256
#endif
/** Rate in Hz that the timer is incremented. */
#define TIMER_RATE (F_CPU / TIMER_CLOCK_DIVISOR)
/** The maximum overrun (in ticks). */
#define TIMER_OVERRUN_MAX 1000
/** The maximum delay (in ticks). */
#define TIMER_DELAY_MAX (65536u - TIMER_OVERRUN_MAX)
/** Define timer ticks. */
typedef uint16_t timer_tick_t;
/** Get current time:
@return current time in ticks. */
timer_tick_t timer_get (void);
/** Wait until specified time:
@param when time to sleep until
@return current time. */
timer_tick_t timer_wait_until (timer_tick_t when);
/** Wait for specified period:
@param period how long to wait
@return current time. */
timer_tick_t timer_wait (timer_tick_t period);
/** Initialise timer. */
void timer_init (void);
#endif /* TIMER_H */