Subversion Repositories idreammicro-avr

Rev

Rev 36 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 jlesech 1
/**************************************************************************//**
2
 * \brief MCP23008 library
3
 * \author Copyright (C) 2012  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 201201025
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 mcp23008.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include <mcp23008/mcp23008.h>
32
 
33
#include <twi/twi.h>
34
#include <useful/bits.h>
35
 
36
#include <stdint.h>
37
 
38
/******************************************************************************
39
 * Private macros.
40
 ******************************************************************************/
41
 
31 jlesech 42
/**************************************************************************//**
43
 * \def     MCP23008__ADDRESS
32 jlesech 44
 * \brief   MCP23008 address on TWI bus (doesn't include hardware address).
31 jlesech 45
 * This value is given by the datasheet.
46
 ******************************************************************************/
56 jlesech 47
#define MCP23008__ADDRESS       0x40
30 jlesech 48
 
31 jlesech 49
/**************************************************************************//**
50
 * \def     MCP23008__REG_IODIR
51
 * \brief   I/O direction register.
52
 ******************************************************************************/
53
#define MCP23008__REG_IODIR     0x00
30 jlesech 54
 
31 jlesech 55
/**************************************************************************//**
56
 * \def     MCP23008__REG_IPOL
57
 * \brief   Input polarity register.
58
 ******************************************************************************/
59
#define MCP23008__REG_IPOL      0x01
30 jlesech 60
 
31 jlesech 61
/**************************************************************************//**
62
 * \def     MCP23008__REG_GPINTEN
63
 * \brief   Interrupt on change control register.
64
 ******************************************************************************/
65
#define MCP23008__REG_GPINTEN   0x02
66
 
67
/**************************************************************************//**
68
 * \def     MCP23008__REG_DEFVAL
69
 * \brief   Default compare register for interrupt on change.
70
 ******************************************************************************/
71
#define MCP23008__REG_DEFVAL    0x03
72
 
73
/**************************************************************************//**
74
 * \def     MCP23008__REG_INTCON
75
 * \brief   Interrupt control register.
76
 ******************************************************************************/
77
#define MCP23008__REG_INTCON    0x04
78
 
79
/**************************************************************************//**
80
 * \def     MCP23008__REG_IOCON
81
 * \brief   Configuration register.
82
 ******************************************************************************/
83
#define MCP23008__REG_IOCON     0x05
84
 
85
/**************************************************************************//**
86
 * \def     MCP23008__REG_GPPU
87
 * \brief   Pull-up resistor configuration register.
88
 ******************************************************************************/
89
#define MCP23008__REG_GPPU      0x06
90
 
91
/**************************************************************************//**
92
 * \def     MCP23008__REG_INTF
93
 * \brief   Interrupt flag register.
94
 ******************************************************************************/
95
#define MCP23008__REG_INTF      0x07
96
 
97
/**************************************************************************//**
98
 * \def     MCP23008__REG_INTCAP
99
 * \brief   Interrupt capture register.
100
 ******************************************************************************/
101
#define MCP23008__REG_INTCAP    0x08
102
 
103
/**************************************************************************//**
104
 * \def     MCP23008__REG_GPIO
105
 * \brief   Port register.
106
 ******************************************************************************/
107
#define MCP23008__REG_GPIO      0x09
108
 
109
/**************************************************************************//**
110
 * \def     MCP23008__REG_OLAT
111
 * \brief   Output latch register.
112
 ******************************************************************************/
113
#define MCP23008__REG_OLAT      0x0A
114
 
30 jlesech 115
/******************************************************************************
116
 * Private function prototypes.
117
 ******************************************************************************/
118
 
119
/**************************************************************************//**
31 jlesech 120
 * \fn static uint8_t mcp23008__read_register(uint8_t address)
30 jlesech 121
 *
31 jlesech 122
 * \brief Read MCP23008 register value.
123
 *
124
 * \param   address Address of the register to read value.
30 jlesech 125
 ******************************************************************************/
126
static
127
uint8_t
128
mcp23008__read_register
129
(
130
    uint8_t address
131
);
132
 
133
/**************************************************************************//**
31 jlesech 134
 * \fn static void mcp23008__write_register(uint8_t address, uint8_t value)
30 jlesech 135
 *
31 jlesech 136
 * \brief Write MCP23008 register value.
137
 *
138
 * \param address   Address of the register to write value.
139
 * \param value     Value to write.
30 jlesech 140
 ******************************************************************************/
141
static
142
void
143
mcp23008__write_register
144
(
31 jlesech 145
    uint8_t address,
146
    uint8_t value
30 jlesech 147
);
148
 
149
/******************************************************************************
150
 * Private variable declarations.
151
 ******************************************************************************/
152
 
153
static uint8_t mcp23008__twi_address = 0;
154
 
155
/******************************************************************************
156
 * Public function definitions.
157
 ******************************************************************************/
158
 
159
/**************************************************************************//**
160
 * \fn void mcp23008__initialize(uint8_t hardware_address)
161
 *
162
 * \brief Initialize MCP23008.
163
 *
31 jlesech 164
 * \param hardware_address  Hardware address defined by pins A0 to A2.
30 jlesech 165
 ******************************************************************************/
166
void
167
mcp23008__initialize
168
(
169
    uint8_t hardware_address
170
){
36 jlesech 171
    // We don't initialize TWI here: we may have several devices on the bus.
30 jlesech 172
    // Initialize TWI.
36 jlesech 173
    //twi__initialize(MCP23008__CLOCK_RATE);
30 jlesech 174
 
175
    // Compute MCP23008 TWI address.
56 jlesech 176
    mcp23008__twi_address = MCP23008__ADDRESS | (hardware_address << 1);
30 jlesech 177
 
178
    twi__start();
179
    twi__send_slaw(mcp23008__twi_address);
180
    twi__send_data(MCP23008__REG_IODIR);
181
    twi__send_data(0xFF);
182
    twi__send_data(0x00);
183
    twi__send_data(0x00);
184
    twi__send_data(0x00);
185
    twi__send_data(0x00);
186
    twi__send_data(0x00);
187
    twi__send_data(0x00);
188
    twi__send_data(0x00);
189
    twi__send_data(0x00);
190
    twi__send_data(0x00);
191
    twi__stop();
192
}
193
 
194
/**************************************************************************//**
31 jlesech 195
 * \fn void mcp23008__configure pin(
196
 * mcp23008__gpio_t         pin,
197
 * mcp23008__direction_t    direction)
30 jlesech 198
 *
31 jlesech 199
 * \brief Configure pin direction.
200
 *
201
 * \param pin       Pin to configure.
202
 * \param direction Pin direction.
30 jlesech 203
 ******************************************************************************/
204
void
205
mcp23008__configure_pin
206
(
207
 
31 jlesech 208
    mcp23008__gpio_t        pin,
209
    mcp23008__direction_t   direction
30 jlesech 210
){
211
    uint8_t port_configuration = mcp23008__read_register(MCP23008__REG_IODIR);
212
 
213
    if (MCP23008__DIRECTION__INPUT == direction)
214
    {
215
        BIT__SET(port_configuration, pin);
216
    }
217
    else
218
    {
219
        BIT__RST(port_configuration, pin);
220
    }
221
 
222
    mcp23008__write_register(MCP23008__REG_IODIR, port_configuration);
223
}
224
 
225
/**************************************************************************//**
31 jlesech 226
 * \fn void mcp23008__configure_port(mcp23008__direction_t direction)
30 jlesech 227
 *
31 jlesech 228
 * \brief Configure port direction.
229
 *
230
 * \param direction Port direction.
30 jlesech 231
 ******************************************************************************/
232
void
233
mcp23008__configure_port
234
(
235
    mcp23008__direction_t direction
236
){
237
    mcp23008__write_register(MCP23008__REG_IODIR, direction);
238
}
239
 
240
/**************************************************************************//**
31 jlesech 241
 * \fn mcp23008__level_t mcp23008__get_pin_level(mcp23008__gpio_t pin)
30 jlesech 242
 *
31 jlesech 243
 * \brief Get pin level.
244
 *
245
 * \param pin   Pin to get level.
246
 *
247
 * \return Pin level.
30 jlesech 248
 ******************************************************************************/
249
mcp23008__level_t
250
mcp23008__get_pin_level
251
(
252
    mcp23008__gpio_t pin
253
){
254
    uint8_t port_value = mcp23008__read_register(MCP23008__REG_GPIO);
255
 
256
    mcp23008__level_t level = BIT__TST(port_value, pin);
257
 
258
    return level;
259
}
260
 
261
/**************************************************************************//**
31 jlesech 262
 * \fn void mcp23008__set_pin_level(
263
 * mcp23008__gpio_t     pin,
264
 * mcp23008__level_t    level)
30 jlesech 265
 *
31 jlesech 266
 * \brief Set pin level.
267
 *
268
 * \param pin   Pin to set level.
269
 * \param level Level to set.
30 jlesech 270
 ******************************************************************************/
271
void
272
mcp23008__set_pin_level
273
(
274
    mcp23008__gpio_t    pin,
275
    mcp23008__level_t   level
276
){
277
    uint8_t port_value = mcp23008__read_register(MCP23008__REG_GPIO);
278
 
279
    if (MCP23008__LEVEL__HIGH == level)
280
    {
281
        BIT__SET(port_value, pin);
282
    }
283
    else
284
    {
285
        BIT__RST(port_value, pin);
286
    }
287
 
288
    mcp23008__write_register(MCP23008__REG_GPIO, port_value);
289
}
290
 
291
/**************************************************************************//**
31 jlesech 292
 * \fn uin8_t mcp23008__get_port_value(void)
30 jlesech 293
 *
31 jlesech 294
 * \brief Get port value.
295
 *
296
 * \return Port value.
30 jlesech 297
 ******************************************************************************/
298
uint8_t
299
mcp23008__get_port_value
300
(
301
    void
302
){
303
    uint8_t value = mcp23008__read_register(MCP23008__REG_GPIO);
304
 
305
    return value;
306
}
307
 
308
/**************************************************************************//**
31 jlesech 309
 * \fn void mcp23008__set_port_value(uint8_t value)
30 jlesech 310
 *
31 jlesech 311
 * \brief Set port value.
312
 *
313
 * \param value Value to set.
30 jlesech 314
 ******************************************************************************/
315
void
316
mcp23008__set_port_value
317
(
318
    uint8_t value
319
){
320
    mcp23008__write_register(MCP23008__REG_GPIO, value);
321
}
322
 
323
/******************************************************************************
324
 * Private function definitions.
325
 ******************************************************************************/
326
 
327
/**************************************************************************//**
31 jlesech 328
 * \fn static uint8_t mcp23008__read_register(uint8_t address)
30 jlesech 329
 *
31 jlesech 330
 * \brief Read MCP23008 register value.
331
 *
332
 * \param   address Address of the register to read value.
30 jlesech 333
 ******************************************************************************/
334
static
335
uint8_t
336
mcp23008__read_register
337
(
338
    uint8_t address
339
){
340
    uint8_t value = 0;
341
 
342
    twi__start();
343
    twi__send_slaw(mcp23008__twi_address);
344
    twi__send_data(address);
345
    twi__stop();
346
 
347
    twi__start();
348
    twi__send_slar(mcp23008__twi_address);
349
    twi__receive_data_nack(&value);
350
    twi__stop();
351
 
352
    return value;
353
}
354
 
355
/**************************************************************************//**
31 jlesech 356
 * \fn static void mcp23008__write_register(uint8_t address, uint8_t value)
30 jlesech 357
 *
31 jlesech 358
 * \brief Write MCP23008 register value.
359
 *
360
 * \param address   Address of the register to write value.
361
 * \param value     Value to write.
30 jlesech 362
 ******************************************************************************/
363
static
364
void
365
mcp23008__write_register
366
(
31 jlesech 367
    uint8_t address,
368
    uint8_t value
30 jlesech 369
){
370
    twi__start();
371
    twi__send_slaw(mcp23008__twi_address);
372
    twi__send_data(address);
373
    twi__send_data(value);
374
    twi__stop();
375
}