Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| Download
| RSS feed
/**************************************************************************//**
* \brief Digital I/O library - Implementation
* \author Copyright (C) 2009 Julien Le Sech - www.idreammicro.com
* \version 1.0
* \date 20090314
*
* This file is part of the iDreamMicro library.
*
* This library is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see http://www.gnu.org/licenses/
******************************************************************************/
/**************************************************************************//**
* \file digital_io.c
******************************************************************************/
/******************************************************************************
* Header file inclusions.
******************************************************************************/
#include <digital_io/digital_io.h>
#include <useful/bits.h>
#include <avr/io.h>
#include <stdint.h>
/******************************************************************************
* Private macro definitions.
******************************************************************************/
/**************************************************************************//**
* \def DIGITAL_IO__PORT_DIRECTION__INPUT
* \brief
******************************************************************************/
#define DIGITAL_IO__PORT_DIRECTION__INPUT 0x00
/**************************************************************************//**
* \def DIGITAL_IO__PORT_DIRECTION__OUTPUT
* \brief
******************************************************************************/
#define DIGITAL_IO__PORT_DIRECTION__OUTPUT 0xFF
/**************************************************************************//**
* \def digital_io__get_index(port)
* \brief
******************************************************************************/
#define digital_io__get_index(port) ((port) >> 4)
/******************************************************************************
* Private types.
******************************************************************************/
/**************************************************************************//**
* \typedef digital_io__register_t
* \brief Digital IO registers (input, output, direction).
******************************************************************************/
typedef struct digital_io__register
{
const uint8_t volatile * const p_input;
uint8_t volatile * const p_output;
uint8_t volatile * const p_direction;
} digital_io__register_t;
/******************************************************************************
* Private variable definitions.
******************************************************************************/
static const digital_io__register_t ports[] =
{
#ifdef PORTA
[digital_io__get_index(DIGITAL_IO__PORT_A)]
{ // PORT A.
.p_input = &PINA,
.p_output = &PORTA,
.p_direction = &DDRA
},
#endif
#ifdef PORTB
[digital_io__get_index(DIGITAL_IO__PORT_B)]
{ // PORT B.
.p_input = &PINB,
.p_output = &PORTB,
.p_direction = &DDRB
},
#endif
#ifdef PORTC
[digital_io__get_index(DIGITAL_IO__PORT_C)]
{ // PORT C.
.p_input = &PINC,
.p_output = &PORTC,
.p_direction = &DDRC
},
#endif
#ifdef PORTD
[digital_io__get_index(DIGITAL_IO__PORT_D)]
{ // PORT D.
.p_input = &PIND,
.p_output = &PORTD,
.p_direction = &DDRD
},
#endif
#ifdef PORTE
[digital_io__get_index(DIGITAL_IO__PORT_E)]
{ // PORT E.
.p_input = &PINE,
.p_output = &PORTE,
.p_direction = &DDRE
},
#endif
#ifdef PORTF
[digital_io__get_index(DIGITAL_IO__PORT_F)]
{ // PORT F.
.p_input = &PINF,
.p_output = &PORTF,
.p_direction = &DDRF
},
#endif
#ifdef PORTG
[digital_io__get_index(DIGITAL_IO__PORT_G)]
{ // PORT G.
.p_input = &PING,
.p_output = &PORTG,
.p_direction = &DDRG
},
#endif
#ifdef PORTH
[digital_io__get_index(DIGITAL_IO__PORT_H)]
{ // PORT H.
.p_input = &PINH,
.p_output = &PORTH,
.p_direction = &DDRH
},
#endif
#ifdef PORTJ
[digital_io__get_index(DIGITAL_IO__PORT_J)]
{ // PORT J.
.p_input = &PINJ,
.p_output = &PORTJ,
.p_direction = &DDRJ
},
#endif
#ifdef PORTK
[digital_io__get_index(DIGITAL_IO__PORT_K)] =
{ // PORT K.
.p_input = &PINK,
.p_output = &PORTK,
.p_direction = &DDRK
},
#endif
#ifdef PORTL
[digital_io__get_index(DIGITAL_IO__PORT_L)]
{ // PORT L.
.p_input = &PINL,
.p_output = &PORTL,
.p_direction = &DDRL
}
#endif
};
/******************************************************************************
* Public function definitions.
******************************************************************************/
/**************************************************************************//**
* \fn void digital_io__configure_pin(
* digital_io__pin_position_t pin_position,
* digital_io__direction_t direction)
*
* \brief Configure a pin.
*
* \param[in] pin_position pin position to configure
* \param direction pin direction
******************************************************************************/
void
digital_io__configure_pin
(
digital_io__pin_position_t pin_position,
digital_io__direction_t direction
){
// Alias.
digital_io__register_t const* p_register =
&(ports[digital_io__get_port(pin_position)]);
if (DIGITAL_IO__DIRECTION__INPUT == direction)
{
BIT__RST(*(p_register->p_direction), digital_io__get_pin(pin_position));
}
else
{
BIT__SET(*(p_register->p_direction), digital_io__get_pin(pin_position));
}
}
/**************************************************************************//**
* \fn digital_io__level_t digital_io__get_pin_level(
* digital_io__pin_position_t pin_position)
*
* \brief Get the level of a pin.
*
* \param pin_position pin position to get level
*
* \return digital io level
******************************************************************************/
digital_io__level_t
digital_io__get_pin_level
(
digital_io__pin_position_t pin_position
){
// Alias.
digital_io__register_t const* p_register =
&(ports[digital_io__get_port(pin_position)]);
digital_io__level_t level =
BIT__TST(*(p_register->p_input), digital_io__get_pin(pin_position)) ?
DIGITAL_IO__LEVEL__HIGH : DIGITAL_IO__LEVEL__LOW;
return level;
}
/**************************************************************************//**
* \fn void digital_io__set_pin_level(
* digital_io__pin_position_t pin_position,
* digital_io__level_t level)
*
* \brief Set the level of a pin.
*
* \param[in] pin_position pin position to set level
* \param level level to set
******************************************************************************/
void
digital_io__set_pin_level
(
digital_io__pin_position_t pin_position,
digital_io__level_t level
){
// Alias.
digital_io__register_t const* p_register =
&(ports[digital_io__get_port(pin_position)]);
if (DIGITAL_IO__LEVEL__LOW == level)
{
BIT__RST(*(p_register->p_output), digital_io__get_pin(pin_position));
}
else
{
BIT__SET(*(p_register->p_output), digital_io__get_pin(pin_position));
}
}
/**************************************************************************//**
* \fn void digital_io__toggle_pin_level(
* digital_io__pin_position_t pin_position)
*
* \brief Toggle the level of a pin.
*
* \param pin_position pin position to toggle level
******************************************************************************/
void
digital_io__toggle_pin_level
(
digital_io__pin_position_t pin_position
){
// Alias.
digital_io__register_t const* p_register =
&(ports[digital_io__get_port(pin_position)]);
BIT__TGL(*(p_register->p_output), digital_io__get_pin(pin_position));
}
/**************************************************************************//**
* \fn void digital_io__configure_port(
* digital_io__port_t port,
* digital_io__direction_t direction)
*
* \brief Configure a port.
*
* \param port port to configure
* \param direction port direction to configure
******************************************************************************/
void
digital_io__configure_port
(
digital_io__port_t port,
digital_io__direction_t direction
){
// Alias.
digital_io__register_t const* p_register =
&(ports[digital_io__get_port(port)]);
if (DIGITAL_IO__DIRECTION__INPUT == direction)
{
*(p_register->p_direction) = DIGITAL_IO__PORT_DIRECTION__INPUT;
}
else
{
*(p_register->p_direction) = DIGITAL_IO__PORT_DIRECTION__OUTPUT;
}
}
/**************************************************************************//**
* \fn uint8_t digital_io__get_port_value(digital_io__port_t port)
*
* \brief Get the value of a port.
*
* \param port port to get value
*
* \return port value
******************************************************************************/
digital_io__port_value_t
digital_io__get_port_value
(
digital_io__port_t port
){
// Alias.
digital_io__register_t const* p_register =
&(ports[digital_io__get_port(port)]);
uint8_t value = *(p_register->p_input);
return value;
}
/**************************************************************************//**
* \fn void digital_io__set_port_value(
* digital_io__port_t port,
* digital_io__port_value_t value)
*
* \brief Set the value of a port.
*
* \param port port to set value
* \param value port value to set
******************************************************************************/
void
digital_io__set_port_value
(
digital_io__port_t port,
digital_io__port_value_t value
){
// Alias.
digital_io__register_t const* p_register =
&(ports[digital_io__get_port(port)]);
*(p_register->p_output) = value;
}