Fichier d'entête

Le fichier d'entête digital_io/digital_io.h constitue l'API de la bibliothèque. Il est situé à la racine de son dossier.

Déclaration d'une broche d'entrée/sortie

Une broche d'entrée/sortie est caractérisée par le port auquel elle appartient et sa position sur le-dit port. Par exemple la broche PB5 est la broche 5 (sixième broche) du port B.

Les différents ports disponibles sont définis par les macros DIGITAL_IO__PORT_x avec x la lettre désignant le port de A à L : DIGITAL_IO__PORT_A à DIGITAL_IO__PORT_L. Par exemple pour le port A :

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_A
 * \brief Port A.
 ******************************************************************************/
#define DIGITAL_IO__PORT_A  0x00

Les différentes broches disponibles sont définies par les macros DIGITAL_IO__PIN_x avec x le numéro de la broche de 0 à 7 : DIGITAL_IO__PIN_0 à DIGITAL_IO__PIN_7. Par exemple pour la broche 0 :

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_0
 * \brief Pin 0.
 ******************************************************************************/
#define DIGITAL_IO__PIN_0   0

Afin de limiter l'empreinte mémoire de multiples déclarations de broches, la position d'une broche est définie sur 1 octet et représentée par le type digital_io__pin_position_t. Les 4 bits de poids fort indiquent le port tandis que les 4 bits de poids faible indiquent le numéro de broche.

Au regard du nombre de fois où on définit des broches d'entrée/sortie, il semble judicieux de privilégier cette solution plutôt qu'une structure comportant les membres port et pin.

/**************************************************************************//**
 * \typedef digital_io__pin_position_t
 * \brief Digital IO pin position.
 * High nibble is used for the port, low nibble is used for the pin.
 * digital_io__pin_position_t pin = DIGITAL_IO__PORT_B | DIGITAL_IO__PIN_5;
 ******************************************************************************/
typedef uint8_t digital_io__pin_position_t;

L'affectation de la position d'une broche d'entrée/sortie se fait de la manière suivante :

// Declare pin.
digital_io__pin_position_t pin = DIGITAL_IO__PORT_B | DIGITAL_IO__PIN_5;

Configuration d'une broche d'entrée/sortie

Une broche d'entrée/sortie peut être configurée en entrée ou en sortie. Ces deux directions sont représentées par l'énumération digital_io__directions et le type digital_io__direction_t.

/**************************************************************************//**
 * \enum digital_io__directions
 * \brief Digital IO directions.
 *
 * \typedef digital_io__direction_t
 * \brief Digital IO direction.
 ******************************************************************************/
typedef enum digital_io__directions
{
    DIGITAL_IO__DIRECTION__INPUT,	/*!<  Input. */
    DIGITAL_IO__DIRECTION__OUTPUT	/*!<  Output. */
} digital_io__direction_t;

Niveau d'une broche d'entrée / sortie

Une broche d'entrée/sortie peut prendre deux niveaux, représentés par l'énumération digital_io__levels et le type digital_io__level_t.

/**************************************************************************//**
 * \enum digital_io__levels
 * \brief Digital IO levels.
 *
 * \typedef digital_io__level_t
 * \brief Digital IO level.
 ******************************************************************************/
typedef enum digital_io__levels
{
    DIGITAL_IO__LEVEL__LOW, /*!<  Low level. */
    DIGITAL_IO__LEVEL__HIGH /*!<  High level. */
} digital_io__level_t;

La bibliothèque digital_io propose différentes fonctions permettant de manipuler les entrées/sorties numériques :

  • digital_io__configure_pin permet de configurer une broche ;
  • digital_io__get_pin_level permet d'obtenir le niveau logique d'une entrée ;
  • digital_io__set_pin_level permet de fixer le niveau logique d'une sortie ;
  • digital_io__toggle_pin_level permet d'inverser le niveau logique d'une sortie ;
  • digital_io__configure_port permet de configurer un port ;
  • digital_io__get_port_value permet d'obtenir le niveau logique des entrées d'un port ;
  • digital_io__set_port_value permet de fixer le niveau logique des sorties d'un port.

Fichier d'entête complet

/**************************************************************************//**
 * \brief Digital I/O library - API
 * \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/
 ******************************************************************************/

/**************************************************************************//**
 * \headerfile digital_io.h
 *
 * \brief
 *
 * \see
 ******************************************************************************/
 
#ifndef H__IDREAMMICRO__DIGITAL_IO__H
#define H__IDREAMMICRO__DIGITAL_IO__H

#ifdef _cplusplus
extern "C"{
#endif

/******************************************************************************
 * Header file inclusions.
 ******************************************************************************/

#include <avr/io.h>

#include <stdint.h>

/******************************************************************************
 * Public macros.
 ******************************************************************************/

/**************************************************************************//**
 * \def digital_io__get_port(pin_position)
 * \brief Get port from pin position.
 ******************************************************************************/
#define digital_io__get_port(pin_position)  ((pin_position) >> 4)

/**************************************************************************//**
 * \def digital_io__get_pin(pin_position)
 * \brief Get pin form pin position.
 ******************************************************************************/
#define digital_io__get_pin(pin_position)   ((pin_position) & 0x0F)

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_A
 * \brief Port A.
 ******************************************************************************/
#define DIGITAL_IO__PORT_A  0x00

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_B
 * \brief Port B.
 ******************************************************************************/
#define DIGITAL_IO__PORT_B  0x10

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_C
 * \brief Port C.
 ******************************************************************************/
#define DIGITAL_IO__PORT_C  0x20

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_D
 * \brief Port D.
 ******************************************************************************/
#define DIGITAL_IO__PORT_D  0x30

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_E
 * \brief Port E.
 ******************************************************************************/
#define DIGITAL_IO__PORT_E  0x40

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_F
 * \brief Port F.
 ******************************************************************************/
#define DIGITAL_IO__PORT_F  0x50

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_G
 * \brief Port G.
 ******************************************************************************/
#define DIGITAL_IO__PORT_G  0x60

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_H
 * \brief port H.
 ******************************************************************************/
#define DIGITAL_IO__PORT_H  0x70 

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_J
 * \brief Port J.
 ******************************************************************************/
#define DIGITAL_IO__PORT_J  0x80

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_K
 * \brief Port K.
 ******************************************************************************/
#define DIGITAL_IO__PORT_K  0x90

/**************************************************************************//**
 * \def DIGITAL_IO__PORT_L
 * \brief Port L.
 ******************************************************************************/
#define DIGITAL_IO__PORT_L  0xA0

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_0
 * \brief Pin 0.
 ******************************************************************************/
#define DIGITAL_IO__PIN_0   0

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_1
 * \brief Pin 1.
 ******************************************************************************/
#define DIGITAL_IO__PIN_1   1

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_2
 * \brief Pin 2.
 ******************************************************************************/
#define DIGITAL_IO__PIN_2   2

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_3
 * \brief Pin 3.
 ******************************************************************************/
#define DIGITAL_IO__PIN_3   3

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_4
 * \brief Pin 4.
 ******************************************************************************/
#define DIGITAL_IO__PIN_4   4

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_5
 * \brief Pin 5.
 ******************************************************************************/
#define DIGITAL_IO__PIN_5   5

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_6
 * \brief Pin 6.
 ******************************************************************************/
#define DIGITAL_IO__PIN_6   6

/**************************************************************************//**
 * \def DIGITAL_IO__PIN_7
 * \brief Pin 7.
 ******************************************************************************/
#define DIGITAL_IO__PIN_7   7

/******************************************************************************
 * Public types.
 ******************************************************************************/

/**************************************************************************//**
 * \typedef digital_io__port_t
 * \brief
 ******************************************************************************/
typedef uint8_t digital_io__port_t;

/**************************************************************************//**
 * \typedef digital_io__pin_t
 * \brief
 ******************************************************************************/
typedef uint8_t digital_io__pin_t;

/**************************************************************************//**
 * \typedef digital_io__pin_position_t
 * \brief Digital IO pin position.
 * High nibble is used for the port, low nibble is used for the pin.
 * digital_io__pin_position_t pin = DIGITAL_IO__PORT_B | DIGITAL_IO__PIN_5;
 ******************************************************************************/
typedef uint8_t digital_io__pin_position_t;

/**************************************************************************//**
 * \enum digital_io__directions
 * \brief Digital IO directions.
 *
 * \typedef digital_io__direction_t
 * \brief Digital IO direction.
 ******************************************************************************/
typedef enum digital_io__directions
{
    DIGITAL_IO__DIRECTION__INPUT,	/*!<  Input. */
    DIGITAL_IO__DIRECTION__OUTPUT	/*!<  Output. */
} digital_io__direction_t;

/**************************************************************************//**
 * \enum digital_io__levels
 * \brief Digital IO levels.
 *
 * \typedef digital_io__level_t
 * \brief Digital IO level.
 ******************************************************************************/
typedef enum digital_io__levels
{
    DIGITAL_IO__LEVEL__LOW, /*!<  Low level. */
    DIGITAL_IO__LEVEL__HIGH	/*!<  High level. */
} digital_io__level_t;

/**************************************************************************//**
 * \typedef digital_io__port_value_t
 * \brief Port value.
 ******************************************************************************/
typedef uint8_t digital_io__port_value_t;

/******************************************************************************
 * Public function prototypes.
 ******************************************************************************/

/**************************************************************************//**
 * \fn void digital_io__configure_pin(
 * digital_io__pin_position_t   pin_position,
 * digital_io__direction_t      direction)
 *
 * \brief Configure a pin.
 *
 * \param   pin_position    pin position to configure
 * \param   direction       pin direction to set
 ******************************************************************************/
void
digital_io__configure_pin
(
    digital_io__pin_position_t  pin_position,
    digital_io__direction_t     direction
);

/**************************************************************************//**
 * \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
);

/**************************************************************************//**
 * \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   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
);

/**************************************************************************//**
 * \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
);

/**************************************************************************//**
 * \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
);

/**************************************************************************//**
 * \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
);

/**************************************************************************//**
 * \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
);

#ifdef _cplusplus
}
#endif

#endif /* H__IDREAMMICRO__DIGITAL_IO__H */

Fichier source

Le fichier source digital_io/src/digital_io.c contient l'implémentation de la bibliothèque.

Représentation d'un port d'entrée/sortie

Un port d'entrée/sortie est caractérisé par différents registres :

  • un registre de configuration DDRx ;
  • un registre d'entrée PINx ;
  • un registre de sortie PORTx.

x désigne la lettre du port, de A à L (DDRA à DDRL, PINA à PINL et PORTA à PORTL).

Il semble alors judicieux de créer la structure digital_io__register et le type digital_io__register_t décrivant un port :

/**************************************************************************//**
 * \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;

Liste des ports d'entrée/sortie

La liste des ports d'entrée/sortie est contenue dans le tableau ports[] :

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
};

Les macros #ifdef PORTx et #endif permettent de renseigner la liste des ports en fonction de ceux réellement disponibles sur le microcontrôleur pour lequel le logiciel est compilé.

Les ports sont insérés dans le tableau par ordre alphabétique. L'utilisation du numéro de port comme index permet de s'affranchir du nombre de ports qui peut varier d'un microcontrôleur à un autre. L'accès à un port est indépendant du type de microcontrôleur.

Cette solution entraîne la perte de quelques octets lorsqu'un port n'est pas disponible sur un microcontrôleur mais a pour avantage de s'adapter à n'importe quelle référence d'ATmega. La maintenance s'en trouve grandement simplifiée.

Fichier source complet

/**************************************************************************//**
 * \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 macros.
 ******************************************************************************/

/**************************************************************************//**
 * \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;
}

Logiciel de démonstration

Le fichier source digital_io__demo.c inclut et utilise la bibliothèque digital_io pour faire basculer le niveau de la sortie PB5 (port B, broche 5).

/**************************************************************************//**
 * \file digital_io__demo.c
 ******************************************************************************/

/******************************************************************************
 * Header file inclusions.
 ******************************************************************************/

#include "../digital_io.h"

#include <util/delay.h>

/******************************************************************************
 * Public function definitions.
 ******************************************************************************/

/**************************************************************************//**
 * \fn void int main(void)
 *
 * \brief Main function.
 *
 * \return 0 if sucess.
 ******************************************************************************/
int
main
(
    void
){
    // Declare pin.
    digital_io__pin_position_t output =
        DIGITAL_IO__PORT_B | DIGITAL_IO__PIN_5;

    // Configure pin direction.
    digital_io__configure_pin(output, DIGITAL_IO__DIRECTION__OUTPUT);

    while (1)
    {
        // Set pin level.
        digital_io__set_pin_level(output, DIGITAL_IO__LEVEL__HIGH);
        _delay_ms(1000);

        // Reset pin level.
        digital_io__set_pin_level(output, DIGITAL_IO__LEVEL__LOW);
        _delay_ms(1000);
    }

    return 0;
}

Conclusion

digital_io, première bibliothèque iDreamMicro est née et est dores et déjà disponible sur le dépôt idreammicro-avr. Vous aurez l'occasion de la retrouver à de nombreuses reprises dans des développements ultérieurs.

N'hésitez pas à l'utiliser, à la modifier et à faire part de vos remarques...