Simplify pio.h and move fast implementation into pio_fast.h

main
Michael Hayes 14 years ago
parent b8039967df
commit 56dca3faf4

@ -1,310 +0,0 @@
/** @file pio-simple.c
@author M. P. Hayes, UCECE
@date 13 Aug 2009
@brief PIO hardware abstraction for AVR microcontroller.
@note This implementation is written for clarity not efficiency.
*/
#include "pio-simple.h"
#define PIO_BITMASK(PIO) (BIT((PIO) & 7)
#define PIO_PORT(PIO) ((PIO) >> 3)
/** Configure pio
@param pio */
bool pio_config_set (pio_t pio, pio_config_t config)
{
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
switch (config)
{
case PIO_INPUT:
DDRB &= ~bitmask;
PORTB &= ~bitmask;
break;
case PIO_PULLUP:
DDRB &= ~bitmask;
PORTB |= bitmask;
break;
case PIO_OUTPUT_LOW:
PORTB &= ~bitmask;
DDRB |= bitmask;
break;
case PIO_OUTPUT_HIGH:
PORTB |= bitmask;
DDRB |= bitmask;
break;
default:
return 0;
}
break;
case PORT_C:
switch (config)
{
case PIO_INPUT:
DDRC &= ~bitmask;
PORTC &= ~bitmask;
break;
case PIO_PULLUP:
DDRC &= ~bitmask;
PORTC |= bitmask;
break;
case PIO_OUTPUT_LOW:
PORTC &= ~bitmask;
DDRC |= bitmask;
break;
case PIO_OUTPUT_HIGH:
PORTC |= bitmask;
DDRC |= bitmask;
break;
default:
return 0;
}
break;
case PORT_D:
switch (config)
{
case PIO_INPUT:
DDRD &= ~bitmask;
PORTD &= ~bitmask;
break;
case PIO_PULLUP:
DDRD &= ~bitmask;
PORTD |= bitmask;
break;
case PIO_OUTPUT_LOW:
PORTD &= ~bitmask;
DDRD |= bitmask;
break;
case PIO_OUTPUT_HIGH:
PORTD |= bitmask;
DDRD |= bitmask;
break;
default:
return 0;
}
break;
default:
return 0;
}
return 1;
}
/** Set pio high.
@param pio */
void pio_output_high (pio_t pio)
{
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
PORTB |= bitmask;
break;
case PORT_C:
PORTC |= bitmask;
break;
case PORT_D:
PORTD |= bitmask;
break;
default:
break;
}
}
/** Set pio low.
@param pio */
void pio_output_low (pio_t pio)
{
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
PORTB &= ~bitmask;
break;
case PORT_C:
PORTC &= ~bitmask;
break;
case PORT_D:
PORTD &= ~bitmask;
break;
default:
break;
}
}
/** Toggle pio.
@param pio */
void pio_output_toggle (pio_t pio)
{
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
PORTB ^= bitmask;
break;
case PORT_C:
PORTC ^= bitmask;
break;
case PORT_D:
PORTD ^= bitmask;
break;
default:
break;
}
}
/** Read input state from pio.
@param pio
@return input state of pio */
bool pio_input_get (pio_t pio)
{
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
return (PINB & bitmask) != 0;
case PORT_C:
return (PINC & bitmask) != 0;
case PORT_D:
return (PIND & bitmask) != 0;
default:
return 0;
}
}
/** Set pio to desired state
@param pio
@param state value to write pio */
void pio_output_set (pio_t pio, bool state)
{
if (state)
pio_output_high (pio);
else
pio_output_low (pio);
}
/** Return pio configuration
@param pio
@return config */
pio_config_t pio_config_get (pio_t pio)
{
bool ddr;
bool port;
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
ddr = (DDRB & bitmask) != 0;
port = (DDRB & bitmask) != 0;
break;
case PORT_C:
ddr = (DDRC & bitmask) != 0;
port = (DDRC & bitmask) != 0;
break;
case PORT_D:
ddr = (DDRD & bitmask) != 0;
port = (DDRD & bitmask) != 0;
break;
default:
return 0;
}
if (ddr)
{
if (port)
return PIO_OUTPUT_HIGH;
else
return PIO_OUTPUT_LOW;
}
if (port)
return PIO_PULLUP;
return PIO_INPUT;
}
/** Get output state of pio.
@param pio
@return output state of pio */
bool pio_output_get (pio_t pio)
{
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
return (PORTB & bitmask) != 0;
case PORT_C:
return (PORTC & bitmask) != 0;
case PORT_D:
return (PORTD & bitmask) != 0;
default:
return 0;
}
}

@ -1,74 +0,0 @@
/** @file pio-simple.h
@author M. P. Hayes, UCECE
@date 11 Jan 2006
@brief PIO hardware abstraction.
*/
#ifndef PIO_H
#define PIO_H
#include "system.h"
#include <avr/io.h>
typedef enum pio_port_enum
{
PORT_A, PORT_B, PORT_C, PORT_D, PORT_E
} pio_port_t;
typedef uint8_t pio_t;
typedef enum pio_config_enum
{
PIO_INPUT = 1, PIO_OUTPUT_LOW, PIO_OUTPUT_HIGH, PIO_PULLUP
} pio_config_t;
/* Define a PIO as a structure in terms of a port and a bit. */
#define PIO_DEFINE(PORT, PORTBIT) ((PORT) * 8 + (PORTBIT))
/** Configure pio.
@param pio */
bool pio_config_set (pio_t pio, pio_config_t config);
/** Configure pio.
@param pio
@return config */
pio_config_t pio_config_get (pio_t pio);
/** Set pio high.
@param pio */
void pio_output_high (pio_t pio);
/** Set pio low.
@param pio */
void pio_output_low (pio_t pio);
/** Toggle pio.
@param pio */
void pio_output_toggle (pio_t pio);
/** Read input state from pio.
@param pio
@return input state of pio */
bool pio_input_get (pio_t pio);
/** Set pio to desired state
@param pio
@param state value to write pio */
void pio_output_set (pio_t pio, bool state);
/** Get output state of pio.
@param pio
@return output state of pio */
bool pio_output_get (pio_t pio);
#endif

@ -2,79 +2,153 @@
@author M. P. Hayes, UCECE
@date 11 Jan 2006
@brief PIO hardware abstraction for AVR microcontroller.
@note Inline functions are used in pio.h instead for performance.
*/
#include "system.h"
#include "pio.h"
#ifdef DEBUG
/** DDR PORT Comment
0 0 High impedance input
0 1 Weak pullup input
1 0 Output low
1 1 Output high
*/
#define PIO_BITMASK(PIO) (BIT((PIO) & 7))
#define PIO_PORT(PIO) ((PIO) >> 3))
/** Configure pio.
@param pio PIO to configure
@param config PIO configuration type
@return non-zero for success. */
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;
uint8_t bitmask;
default:
return 0;
}
}
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
switch (config)
{
case PIO_INPUT:
DDRB &= ~bitmask;
PORTB &= ~bitmask;
break;
case PIO_PULLUP:
DDRB &= ~bitmask;
PORTB |= bitmask;
break;
case PIO_OUTPUT_LOW:
PORTB &= ~bitmask;
DDRB |= bitmask;
break;
/** Return pio configuration
@param pio
@return config */
pio_config_t pio_config_get (pio_t pio)
{
bool ddr;
bool port;
case PIO_OUTPUT_HIGH:
PORTB |= bitmask;
DDRB |= bitmask;
break;
default:
return 0;
}
break;
case PORT_C:
switch (config)
{
case PIO_INPUT:
DDRC &= ~bitmask;
PORTC &= ~bitmask;
break;
case PIO_PULLUP:
DDRC &= ~bitmask;
PORTC |= bitmask;
break;
case PIO_OUTPUT_LOW:
PORTC &= ~bitmask;
DDRC |= bitmask;
break;
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;
case PIO_OUTPUT_HIGH:
PORTC |= bitmask;
DDRC |= bitmask;
break;
default:
return 0;
}
break;
case PORT_D:
switch (config)
{
case PIO_INPUT:
DDRD &= ~bitmask;
PORTD &= ~bitmask;
break;
case PIO_PULLUP:
DDRD &= ~bitmask;
PORTD |= bitmask;
break;
case PIO_OUTPUT_LOW:
PORTD &= ~bitmask;
DDRD |= bitmask;
break;
case PIO_OUTPUT_HIGH:
PORTD |= bitmask;
DDRD |= bitmask;
break;
default:
return 0;
}
break;
default:
return 0;
}
if (port)
return PIO_PULLUP;
return PIO_INPUT;
return 1;
}
/** Set pio high.
@param pio */
void pio_output_high (pio_t pio)
{
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
PORTB |= bitmask;
break;
case PORT_C:
PORTC |= bitmask;
break;
case PORT_D:
PORTD |= bitmask;
break;
default:
break;
}
}
@ -82,7 +156,27 @@ void pio_output_high (pio_t pio)
@param pio */
void pio_output_low (pio_t pio)
{
PIO_DATA_ (pio) &= ~PIO_BITMASK_ (pio);
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
PORTB &= ~bitmask;
break;
case PORT_C:
PORTC &= ~bitmask;
break;
case PORT_D:
PORTD &= ~bitmask;
break;
default:
break;
}
}
@ -90,7 +184,27 @@ void pio_output_low (pio_t pio)
@param pio */
void pio_output_toggle (pio_t pio)
{
PIO_DATA_ (pio) ^= PIO_BITMASK_ (pio);
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
PORTB ^= bitmask;
break;
case PORT_C:
PORTC ^= bitmask;
break;
case PORT_D:
PORTD ^= bitmask;
break;
default:
break;
}
}
@ -99,25 +213,110 @@ void pio_output_toggle (pio_t pio)
@return input state of pio */
bool pio_input_get (pio_t pio)
{
return (PIO_PIN_ (pio) & PIO_BITMASK_ (pio)) != 0;
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
return (PINB & bitmask) != 0;
case PORT_C:
return (PINC & bitmask) != 0;
case PORT_D:
return (PIND & bitmask) != 0;
default:
return 0;
}
}
/** Get output state of pio.
/** Set pio to desired state
@param pio
@return output state of pio */
bool pio_output_get (pio_t pio)
@param state value to write pio */
void pio_output_set (pio_t pio, bool state)
{
return (PIO_DATA_ (pio) & PIO_BITMASK_ (pio)) != 0;
if (state)
pio_output_high (pio);
else
pio_output_low (pio);
}
/** Set pio to desired state.
/** Return pio configuration
@param pio
@return config */
pio_config_t pio_config_get (pio_t pio)
{
bool ddr;
bool port;
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
ddr = (DDRB & bitmask) != 0;
port = (DDRB & bitmask) != 0;
break;
case PORT_C:
ddr = (DDRC & bitmask) != 0;
port = (DDRC & bitmask) != 0;
break;
case PORT_D:
ddr = (DDRD & bitmask) != 0;
port = (DDRD & bitmask) != 0;
break;
default:
return 0;
}
if (ddr)
{
if (port)
return PIO_OUTPUT_HIGH;
else
return PIO_OUTPUT_LOW;
}
if (port)
return PIO_PULLUP;
return PIO_INPUT;
}
/** Get output state of pio.
@param pio
@param state value to write pio */
void pio_output_set (pio_t pio, bool state)
@return output state of pio */
bool pio_output_get (pio_t pio)
{
state ? pio_output_high (pio) : pio_output_low (pio);
uint8_t bitmask;
bitmask = PIO_BITMASK (pio);
switch (PIO_PORT (pio))
{
case PORT_B:
return (PORTB & bitmask) != 0;
case PORT_C:
return (PORTC & bitmask) != 0;
case PORT_D:
return (PORTD & bitmask) != 0;
default:
return 0;
}
}
#endif

@ -2,8 +2,6 @@
@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
@ -39,12 +37,10 @@
#endif
/** Define port names, note not all the ports are available on some AVRs. */
/** Define port names; note not all the ports are available on some AVRs. */
enum {PORT_A, PORT_B, PORT_C, PORT_D, PORT_E, PORT_F, PORT_G};
typedef volatile uint8_t *pio_port_t;
typedef uint8_t pio_mask_t;
typedef uint16_t pio_t;
@ -54,53 +50,18 @@ typedef uint16_t pio_t;
typedef enum pio_config_enum
{
PIO_INPUT = 1, /** Configure as input pin. */
PIO_PULLUP, /** Configure as input pin with pullup. */
PIO_PULLUP, /** Configure as input pin with pullup enabled. */
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 unique 16 bit number encoding the low part of
the PORT address offset in the low byte and the bit mask in the
high byte. PORTB is used for the pattern since PORTA is not
always defined for some AVRs. */
#define PIO_DEFINE(PORT, PORTBIT) ((((PORT) - PORT_B) * 3) | (BIT(PORTBIT) << 8))
/** Private macro to lookup bitmask. */
#define PIO_BITMASK_(PIO) ((PIO) >> 8)
/** Private macro to lookup port register. */
#define PIO_PORT_(PIO) (&PORTB + ((PIO) & 0xff))
/** 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)))
#ifdef DEBUG
/** Private macro to access a pio data register. */
#define PIO_DATA_(PIO) (*PIO_PORT_ (PIO))
/* Define a PIO as a structure in terms of a port and a bit. */
#define PIO_DEFINE(PORT, PORTBIT) ((PORT) * 8 + (PORTBIT))
#ifdef DEBUG
/** Configure pio.
@param pio PIO to configure
@param config PIO configuration type
@ -148,123 +109,9 @@ void pio_output_set (pio_t pio, bool state);
#else
/** 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);
}
/* Use fast PIO implementation instead. */
#include "pio_fast.h"
/** 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);
}
#endif
#endif

@ -0,0 +1,167 @@
/** @file pio-fast.h
@author M. P. Hayes, UCECE
@date 11 Jan 2006
@brief Fast 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.
*/
#ifndef PIO_FAST_H
#define PIO_FAST_H
#include "system.h"
#ifdef AVR
#include <avr/io.h>
#endif
/** Define a PIO as a unique 16 bit number encoding the low part of
the PORT address offset in the low byte and the bit mask in the
high byte. PORTB is used for the pattern since PORTA is not
always defined for some AVRs. */
#define PIO_DEFINE(PORT, PORTBIT) ((((PORT) - PORT_B) * 3) | (BIT(PORTBIT) << 8))
/** Private macro to lookup bitmask. */
#define PIO_BITMASK_(PIO) ((PIO) >> 8)
/** Private macro to lookup port register. */
#define PIO_PORT_(PIO) (&PORTB + ((PIO) & 0xff))
/** 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);
}
#endif
Loading…
Cancel
Save