Subversion Repositories idreammicro-avr

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 jlesech 1
/**************************************************************************//**
2
 * \brief Digital I/O library - Implementation
3
 * \author Copyright (C) 2009  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 20090314
6
 *
7
 * This file is part of the iDreamMicro library.
8
 *
9
 * This library is free software: you can redistribute it and/or modify it under
10
 * the terms of the GNU Lesser General Public License as published by the Free
11
 * Software Foundation, either version 3 of the License, or (at your option) any
12
 * later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program. If not, see http://www.gnu.org/licenses/
21
 ******************************************************************************/
22
 
23
/**************************************************************************//**
24
 * \file digital_io.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include <digital_io/digital_io.h>
32
#include <useful/bits.h>
33
 
34
#include <avr/io.h>
35
 
36
#include <stdint.h>
37
 
38
/******************************************************************************
39
 * Private macro definitions.
40
 ******************************************************************************/
41
 
42
/**************************************************************************//**
43
 * \def DIGITAL_IO__PORT_DIRECTION__INPUT
44
 * \brief
45
 ******************************************************************************/
46
#define DIGITAL_IO__PORT_DIRECTION__INPUT   0x00
47
 
48
/**************************************************************************//**
49
 * \def DIGITAL_IO__PORT_DIRECTION__OUTPUT
50
 * \brief
51
 ******************************************************************************/
52
#define DIGITAL_IO__PORT_DIRECTION__OUTPUT  0xFF
53
 
54
/**************************************************************************//**
55
 * \def digital_io__get_index(port)
56
 * \brief
57
 ******************************************************************************/
58
#define digital_io__get_index(port)         ((port) >> 4)
59
 
60
/******************************************************************************
61
 * Private types.
62
 ******************************************************************************/
63
 
64
/**************************************************************************//**
65
 * \typedef digital_io__register_t
66
 * \brief Digital IO registers (input, output, direction).
67
 ******************************************************************************/
68
typedef struct digital_io__register
69
{
70
    const uint8_t volatile * const  p_input;
71
    uint8_t volatile * const        p_output;
72
    uint8_t volatile * const        p_direction;
73
} digital_io__register_t;
74
 
75
/******************************************************************************
76
 * Private variable definitions.
77
 ******************************************************************************/
78
 
79
static const digital_io__register_t ports[] =
80
{
81
    #ifdef PORTA
82
    [digital_io__get_index(DIGITAL_IO__PORT_A)]
83
    { // PORT A.
84
        .p_input                = &PINA,
85
        .p_output               = &PORTA,
86
        .p_direction    = &DDRA
87
    },
88
    #endif
89
    #ifdef PORTB
90
    [digital_io__get_index(DIGITAL_IO__PORT_B)]
91
    { // PORT B.
92
        .p_input                = &PINB,
93
        .p_output               = &PORTB,
94
        .p_direction    = &DDRB
95
    },
96
    #endif
97
    #ifdef PORTC
98
    [digital_io__get_index(DIGITAL_IO__PORT_C)]
99
    { // PORT C.
100
        .p_input                = &PINC,
101
        .p_output               = &PORTC,
102
        .p_direction    = &DDRC
103
    },
104
    #endif
105
    #ifdef PORTD
106
    [digital_io__get_index(DIGITAL_IO__PORT_D)]
107
    { // PORT D.
108
        .p_input                = &PIND,
109
        .p_output               = &PORTD,
110
        .p_direction    = &DDRD
111
    },
112
    #endif
113
    #ifdef PORTE
114
    [digital_io__get_index(DIGITAL_IO__PORT_E)]
115
    { // PORT E.
116
        .p_input                = &PINE,
117
        .p_output               = &PORTE,
118
        .p_direction    = &DDRE
119
    },
120
    #endif
121
    #ifdef PORTF
122
    [digital_io__get_index(DIGITAL_IO__PORT_F)]
123
    { // PORT F.
124
        .p_input                = &PINF,
125
        .p_output               = &PORTF,
126
        .p_direction    = &DDRF
127
    },
128
    #endif
129
    #ifdef PORTG
130
    [digital_io__get_index(DIGITAL_IO__PORT_G)]
131
    { // PORT G.
132
        .p_input                = &PING,
133
        .p_output               = &PORTG,
134
        .p_direction    = &DDRG
135
    },
136
    #endif
137
    #ifdef PORTH
138
    [digital_io__get_index(DIGITAL_IO__PORT_H)]
139
    { // PORT H.
140
        .p_input                = &PINH,
141
        .p_output               = &PORTH,
142
        .p_direction    = &DDRH
143
    },
144
    #endif
145
    #ifdef PORTJ
146
    [digital_io__get_index(DIGITAL_IO__PORT_J)]
147
    { // PORT J.
148
        .p_input                = &PINJ,
149
        .p_output               = &PORTJ,
150
        .p_direction    = &DDRJ
151
    },
152
    #endif
153
    #ifdef PORTK
154
    [digital_io__get_index(DIGITAL_IO__PORT_K)] =
155
    { // PORT K.
156
        .p_input                = &PINK,
157
        .p_output               = &PORTK,
158
        .p_direction    = &DDRK
159
    },
160
    #endif
161
    #ifdef PORTL
162
    [digital_io__get_index(DIGITAL_IO__PORT_L)]
163
    { // PORT L.
164
        .p_input                = &PINL,
165
        .p_output               = &PORTL,
166
        .p_direction    = &DDRL
167
    }
168
    #endif
169
};
170
 
171
/******************************************************************************
172
 * Public function definitions.
173
 ******************************************************************************/
174
 
175
/**************************************************************************//**
176
 * \fn void digital_io__configure_pin(
177
 * digital_io__pin_position_t   pin_position,
178
 * digital_io__direction_t      direction)
179
 *
180
 * \brief Configure a pin.
181
 *
182
 * \param[in]   pin_position    pin position to configure
183
 * \param       direction       pin direction
184
 ******************************************************************************/
185
void
186
digital_io__configure_pin
187
(
188
        digital_io__pin_position_t  pin_position,
189
        digital_io__direction_t     direction
190
){
191
        // Alias.
192
        digital_io__register_t const* p_register =
193
        &(ports[digital_io__get_port(pin_position)]);
194
 
195
        if (DIGITAL_IO__DIRECTION__INPUT == direction)
196
        {
197
        BIT__RST(*(p_register->p_direction), digital_io__get_pin(pin_position));
198
        }
199
        else
200
        {
201
        BIT__SET(*(p_register->p_direction), digital_io__get_pin(pin_position));
202
        }
203
}
204
 
205
/**************************************************************************//**
206
 * \fn digital_io__level_t digital_io__get_pin_level(
207
 * digital_io__pin_position_t pin_position)
208
 *
209
 * \brief Get the level of a pin.
210
 *
211
 * \param   pin_position    pin position to get level
212
 *
213
 * \return digital io level
214
 ******************************************************************************/
215
digital_io__level_t
216
digital_io__get_pin_level
217
(
218
        digital_io__pin_position_t  pin_position
219
){
220
        // Alias.
221
        digital_io__register_t const* p_register =
222
        &(ports[digital_io__get_port(pin_position)]);
223
 
224
        digital_io__level_t level =
225
        BIT__TST(*(p_register->p_input), digital_io__get_pin(pin_position)) ?
226
                DIGITAL_IO__LEVEL__HIGH : DIGITAL_IO__LEVEL__LOW;
227
 
228
        return level;
229
}
230
 
231
/**************************************************************************//**
232
 * \fn void digital_io__set_pin_level(
233
 * digital_io__pin_position_t   pin_position,
234
 * digital_io__level_t          level)
235
 *
236
 * \brief Set the level of a pin.
237
 *
238
 * \param[in]   pin_position    pin position to set level
239
 * \param       level           level to set
240
 ******************************************************************************/
241
void
242
digital_io__set_pin_level
243
(
244
        digital_io__pin_position_t  pin_position,
245
        digital_io__level_t         level
246
){
247
        // Alias.
248
        digital_io__register_t const* p_register =
249
        &(ports[digital_io__get_port(pin_position)]);
250
 
251
        if (DIGITAL_IO__LEVEL__LOW == level)
252
        {
253
        BIT__RST(*(p_register->p_output), digital_io__get_pin(pin_position));
254
        }
255
        else
256
        {
257
        BIT__SET(*(p_register->p_output), digital_io__get_pin(pin_position));
258
        }
259
}
260
 
261
/**************************************************************************//**
262
 * \fn void digital_io__toggle_pin_level(
263
 * digital_io__pin_position_t pin_position)
264
 *
265
 * \brief Toggle the level of a pin.
266
 *
267
 * \param   pin_position    pin position to toggle level
268
 ******************************************************************************/
269
void
270
digital_io__toggle_pin_level
271
(
272
        digital_io__pin_position_t  pin_position
273
){
274
    // Alias.
275
    digital_io__register_t const* p_register =
276
        &(ports[digital_io__get_port(pin_position)]);
277
 
278
    BIT__TGL(*(p_register->p_output), digital_io__get_pin(pin_position));
279
}
280
 
281
/**************************************************************************//**
282
 * \fn void digital_io__configure_port(
283
 * digital_io__port_t       port,
284
 * digital_io__direction_t  direction)
285
 *
286
 * \brief Configure a port.
287
 *
288
 * \param   port        port to configure
289
 * \param   direction   port direction to configure
290
 ******************************************************************************/
291
void
292
digital_io__configure_port
293
(
294
    digital_io__port_t      port,
295
    digital_io__direction_t direction
296
){
297
        // Alias.
298
        digital_io__register_t const* p_register =
299
        &(ports[digital_io__get_port(port)]);
300
 
301
        if (DIGITAL_IO__DIRECTION__INPUT == direction)
302
        {
303
                *(p_register->p_direction) = DIGITAL_IO__PORT_DIRECTION__INPUT;
304
        }
305
        else
306
        {
307
                *(p_register->p_direction) = DIGITAL_IO__PORT_DIRECTION__OUTPUT;
308
        }
309
}
310
 
311
/**************************************************************************//**
312
 * \fn uint8_t digital_io__get_port_value(digital_io__port_t port)
313
 *
314
 * \brief Get the value of a port.
315
 *
316
 * \param   port    port to get value
317
 *
318
 * \return port value
319
 ******************************************************************************/
320
digital_io__port_value_t
321
digital_io__get_port_value
322
(
323
    digital_io__port_t  port
324
){
325
        // Alias.
326
        digital_io__register_t const* p_register =
327
        &(ports[digital_io__get_port(port)]);
328
 
329
        uint8_t value = *(p_register->p_input);
330
 
331
        return value;
332
}
333
 
334
/**************************************************************************//**
335
 * \fn void digital_io__set_port_value(
336
 * digital_io__port_t       port,
337
 * digital_io__port_value_t value)
338
 *
339
 * \brief Set the value of a port.
340
 *
341
 * \param   port  port to set value
342
 * \param   value port value to set
343
 ******************************************************************************/
344
void
345
digital_io__set_port_value
346
(
347
    digital_io__port_t          port,
348
    digital_io__port_value_t    value
349
){
350
        // Alias.
351
        digital_io__register_t const* p_register =
352
        &(ports[digital_io__get_port(port)]);
353
 
354
        *(p_register->p_output) = value;
355
}