Simplify pio.h and move fast implementation into pio_fast.h
This commit is contained in:
@@ -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
|
||||
+261
-62
@@ -2,44 +2,247 @@
|
||||
@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)
|
||||
{
|
||||
uint8_t bitmask;
|
||||
|
||||
bitmask = PIO_BITMASK (pio);
|
||||
|
||||
switch (PIO_PORT (pio))
|
||||
{
|
||||
case PORT_B:
|
||||
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;
|
||||
DDRB &= ~bitmask;
|
||||
PORTB &= ~bitmask;
|
||||
break;
|
||||
|
||||
case PIO_PULLUP:
|
||||
PIO_DDR_ (pio) &= ~PIO_BITMASK_ (pio);
|
||||
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
|
||||
return 1;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +253,30 @@ pio_config_t pio_config_get (pio_t pio)
|
||||
{
|
||||
bool ddr;
|
||||
bool port;
|
||||
uint8_t bitmask;
|
||||
|
||||
ddr = PIO_DDR_ (pio) & PIO_BITMASK_ (pio);
|
||||
port = PIO_DATA_ (pio) & PIO_BITMASK_ (pio);
|
||||
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)
|
||||
{
|
||||
@@ -69,55 +293,30 @@ pio_config_t pio_config_get (pio_t pio)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Set pio high.
|
||||
@param pio */
|
||||
void pio_output_high (pio_t pio)
|
||||
{
|
||||
PIO_DATA_ (pio) |= PIO_BITMASK_ (pio);
|
||||
}
|
||||
|
||||
|
||||
/** Set pio low.
|
||||
@param pio */
|
||||
void pio_output_low (pio_t pio)
|
||||
{
|
||||
PIO_DATA_ (pio) &= ~PIO_BITMASK_ (pio);
|
||||
}
|
||||
|
||||
|
||||
/** Toggle pio.
|
||||
@param pio */
|
||||
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 */
|
||||
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 */
|
||||
bool pio_output_get (pio_t pio)
|
||||
{
|
||||
return (PIO_DATA_ (pio) & PIO_BITMASK_ (pio)) != 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Set pio to desired state.
|
||||
@param pio
|
||||
@param state value to write pio */
|
||||
void pio_output_set (pio_t pio, bool state)
|
||||
{
|
||||
state ? pio_output_high (pio) : pio_output_low (pio);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+9
-162
@@ -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)))
|
||||
|
||||
|
||||
/** Private macro to access a pio data register. */
|
||||
#define PIO_DATA_(PIO) (*PIO_PORT_ (PIO))
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/* 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 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;
|
||||
/* Use fast PIO implementation instead. */
|
||||
#include "pio_fast.h"
|
||||
|
||||
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
|
||||
|
||||
#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
|
||||
Reference in New Issue
Block a user