Statistics
| Branch: | Tag: | Revision:

amiro-lld / source / alld_pcal6524.c @ e3287406

History | View | Annotate | Download (11 KB)

1 e3287406 Thomas Schöpping
/*
2
AMiRo-LLD is a compilation of low-level hardware drivers for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2019  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU Lesser General Public License for more details.
14

15
You should have received a copy of the GNU Lesser General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
/**
20
 * @file    alld_pcal6524.c
21
 * @brief   GPIO extender function implementations.
22
 *
23
 * @addtogroup lld_gpioext
24
 * @{
25
 */
26
27
#include <alld_pcal6524.h>
28
29
#if defined(AMIROLLD_CFG_USE_PCAL6524) || defined(__DOXYGEN__)
30
31
#include <string.h>
32
33
/*============================================================================*/
34
/* local constants and functions                                              */
35
/*============================================================================*/
36
37
#define _MAXIMUM_GROUP_SIZE           6
38
39
/*============================================================================*/
40
/* helper functions                                                           */
41
/*============================================================================*/
42
43
/**
44
 * @brief   Returns the size of the group for a specified command.
45
 *
46
 * @param[in] cmd   Command to retrieve the group size for.
47
 *
48
 * @return    The size of the group in bytes.
49
 */
50
inline uint8_t pcal6524_lld_cmd_groupsize(const pcal6524_lld_cmd_t cmd)
51
{
52
  switch (cmd) {
53
    case PCAL6524_LLD_CMD_OUTPUTCONFIGURATION:
54
    case PCAL6524_LLD_CMD_SWITCHDEBOUNCECOUNT:
55
      return 1;
56
    case PCAL6524_LLD_CMD_SWITCHDEBOUNCEENABLE_P0:
57
    case PCAL6524_LLD_CMD_SWITCHDEBOUNCEENABLE_P1:
58
      return 2;
59
    case PCAL6524_LLD_CMD_INPUT_P0:
60
    case PCAL6524_LLD_CMD_INPUT_P1:
61
    case PCAL6524_LLD_CMD_INPUT_P2:
62
    case PCAL6524_LLD_CMD_OUTPUT_P0:
63
    case PCAL6524_LLD_CMD_OUTPUT_P1:
64
    case PCAL6524_LLD_CMD_OUTPUT_P2:
65
    case PCAL6524_LLD_CMD_POLARITYINVERSION_P0:
66
    case PCAL6524_LLD_CMD_POLARITYINVERSION_P1:
67
    case PCAL6524_LLD_CMD_POLARITYINVERSION_P2:
68
    case PCAL6524_LLD_CMD_CONFIGURATION_P0:
69
    case PCAL6524_LLD_CMD_CONFIGURATION_P1:
70
    case PCAL6524_LLD_CMD_CONFIGURATION_P2:
71
    case PCAL6524_LLD_CMD_INPUTLATCH_P0:
72
    case PCAL6524_LLD_CMD_INPUTLATCH_P1:
73
    case PCAL6524_LLD_CMD_INPUTLATCH_P2:
74
    case PCAL6524_LLD_CMD_PUPDENABLE_P0:
75
    case PCAL6524_LLD_CMD_PUPDENABLE_P1:
76
    case PCAL6524_LLD_CMD_PUPDENABLE_P2:
77
    case PCAL6524_LLD_CMD_PUPDSELECTION_P0:
78
    case PCAL6524_LLD_CMD_PUPDSELECTION_P1:
79
    case PCAL6524_LLD_CMD_PUPDSELECTION_P2:
80
    case PCAL6524_LLD_CMD_INTERRUPTMASK_P0:
81
    case PCAL6524_LLD_CMD_INTERRUPTMASK_P1:
82
    case PCAL6524_LLD_CMD_INTERRUPTMASK_P2:
83
    case PCAL6524_LLD_CMD_INTERRUPTSTATUS_P0:
84
    case PCAL6524_LLD_CMD_INTERRUPTSTATUS_P1:
85
    case PCAL6524_LLD_CMD_INTERRUPTSTATUS_P2:
86
    case PCAL6524_LLD_CMD_INTERRUPTCLEAR_P0:
87
    case PCAL6524_LLD_CMD_INTERRUPTCLEAR_P1:
88
    case PCAL6524_LLD_CMD_INTERRUPTCLEAR_P2:
89
    case PCAL6524_LLD_CMD_INPUTSTATUS_P0:
90
    case PCAL6524_LLD_CMD_INPUTSTATUS_P1:
91
    case PCAL6524_LLD_CMD_INPUTSTATUS_P2:
92
    case PCAL6524_LLD_CMD_INDIVIDUALPINOUTPUTCONFIGURATION_P0:
93
    case PCAL6524_LLD_CMD_INDIVIDUALPINOUTPUTCONFIGURATION_P1:
94
    case PCAL6524_LLD_CMD_INDIVIDUALPINOUTPUTCONFIGURATION_P2:
95
      return 3;
96
    case PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P0A:
97
    case PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P0B:
98
    case PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P1A:
99
    case PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P1B:
100
    case PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P2A:
101
    case PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P2B:
102
    case PCAL6524_LLD_CMD_INTERRUPTEDGE_P0A:
103
    case PCAL6524_LLD_CMD_INTERRUPTEDGE_P0B:
104
    case PCAL6524_LLD_CMD_INTERRUPTEDGE_P1A:
105
    case PCAL6524_LLD_CMD_INTERRUPTEDGE_P1B:
106
    case PCAL6524_LLD_CMD_INTERRUPTEDGE_P2A:
107
    case PCAL6524_LLD_CMD_INTERRUPTEDGE_P2B:
108
      return 6;
109
  }
110
  // must never occur
111
  apalDbgAssert(false);
112
  return 0;
113
}
114
115
/*============================================================================*/
116
/* general register access                                                    */
117
/*============================================================================*/
118
119
// Reading the ID is currently not supported, since the required I²C sequence can not trivially executed via periphAL and ChibiOS/HAL.
120
///**
121
// * @brief   Read device ID and manufacturer information.
122
// *
123
// * @param[in]   pcal6524d   The PCAL6524 driver to use.
124
// * @param[out]  info        Pointer where to store the information data.
125
// * @param[in]   timeout     Timeout for the function to return.
126
// *
127
// * @return    Indicator whether the function call was successful or a timeout occurred.
128
// */
129
//inline apalExitStatus_t
130
//pcal6524_lld_read_id(const PCAL6524Driver* const pcal6524d, pcal6524_lld_deviceid_t* const info, const apalTime_t timeout)
131
//{
132
//  apalDbgAssert(pcal6524d != NULL && pcal6524d->i2cd != NULL);
133
//  apalDbgAssert(info != NULL);
134
//
135
//  const uint8_t txbuf = (uint8_t)pcal6524d->addr;
136
//  return apalI2CMasterTransmit(pcal6524d->i2cd, PCAL6524_LLD_I2C_ADDR_DEVICEID, &txbuf, 1, info->raw, sizeof(info->raw), timeout);
137
//}
138
139
/**
140
 * @brief   Read 8bit data from any register.
141
 *
142
 * @param[in]   pcal6524d       The PCAL6524 driver to use.
143
 * @param[in]   reg             Command register to read.
144
 * @param[out]  data            Pointer to store the register data to.
145
 * @param[in]   timeout         Timeout for the function to return (in microseconds).
146
 *
147
 * @return    Indicator whether the function call was successful or a timeout occurred.
148
 */
149
inline apalExitStatus_t
150
pcal6524_lld_read_reg(const PCAL6524Driver* const pcal6524d, const pcal6524_lld_cmd_t reg, uint8_t* const data, const apalTime_t timeout)
151
{
152
  apalDbgAssert(pcal6524d != NULL && pcal6524d->i2cd != NULL);
153
  apalDbgAssert(data != NULL);
154
155
  const uint8_t txbuf = (uint8_t)reg;
156
  return apalI2CMasterTransmit(pcal6524d->i2cd, pcal6524d->addr, &txbuf, 1, data, 1, timeout);
157
}
158
159
/**
160
 * @brief   Write 8bit data to any (writable) register.
161
 *
162
 * @param[in]   pcal6524d       The PCAL6524 driver to use.
163
 * @param[in]   reg             Command register to write to.
164
 * @param[in]   data            Data to transmit.
165
 * @param[in]   timeout         Timout for the function to return (in microseconds).
166
 *
167
 * @return    Indicator whether the function call was successful or a timeout occurred.
168
 */
169
inline apalExitStatus_t
170
pcal6524_lld_write_reg(const PCAL6524Driver* const pcal6524d, const pcal6524_lld_cmd_t reg, const uint8_t data, const apalTime_t timeout)
171
{
172
  apalDbgAssert(pcal6524d != NULL && pcal6524d->i2cd != NULL);
173
174
  uint8_t txbuf[2] = { (uint8_t)reg, data };
175
  return apalI2CMasterTransmit(pcal6524d->i2cd, pcal6524d->addr, txbuf, 2, NULL, 0, timeout);
176
}
177
178
/**
179
 * @brief   Read register group starting with an arbitrary register.
180
 *
181
 * @param[in]   pcal6524d   The PCAL6524 driver to use.
182
 * @param[in]   reg         Command register to start at.
183
 * @param[out]  data        Pointer to store rhe group data to.
184
 *                          The reqired number of bytes depends on the group.
185
 * @param[in]   timeout     Timeout for the function to return (in microseconds).
186
 *
187
 * @return    Indicator whether the function call was successful or a timeout occurred.
188
 */
189
inline apalExitStatus_t
190
pcal6524_lld_read_group(const PCAL6524Driver* const pcal6524d, const pcal6524_lld_cmd_t reg, uint8_t* const data, const apalTime_t timeout)
191
{
192
  apalDbgAssert(pcal6524d != NULL && pcal6524d->i2cd != NULL);
193
  apalDbgAssert(data != NULL);
194
195
  const uint8_t txbuf = (uint8_t)reg;
196
  return apalI2CMasterTransmit(pcal6524d->i2cd, pcal6524d->addr, &txbuf, 1, data, pcal6524_lld_cmd_groupsize(reg), timeout);
197
}
198
199
/**
200
 * @brief   Write register group data to any (writable) register.
201
 *
202
 * @param[in]   pcal6524d       The PCAL6524 driver to use.
203
 * @param[in]   reg             Command register to start at.
204
 * @param[in]   data            Data to transmit.
205
 *                              The reqired number of bytes depends on the group.
206
 * @param[in]   timeout         Timout for the function to return (in microseconds).
207
 *
208
 * @return    Indicator whether the function call was successful or a timeout occurred.
209
 */
210
inline apalExitStatus_t
211
pcal6524_lld_write_group(const PCAL6524Driver* const pcal6524d, const pcal6524_lld_cmd_t reg, const uint8_t* const data, const apalTime_t timeout)
212
{
213
  apalDbgAssert(pcal6524d != NULL && pcal6524d->i2cd != NULL);
214
  apalDbgAssert(data != NULL);
215
216
  uint8_t txbuf[_MAXIMUM_GROUP_SIZE + 1] = {(uint8_t)reg};
217
  memcpy(&txbuf[1], data, pcal6524_lld_cmd_groupsize(reg));
218
  return apalI2CMasterTransmit(pcal6524d->i2cd, pcal6524d->addr, txbuf, pcal6524_lld_cmd_groupsize(reg) + 1, NULL, 0, timeout);
219
}
220
221
/**
222
 * @brief   Read multiple registers continously, starting at an arbitrary one.
223
 *
224
 * @param[in]   pcal6524d   The PCAL6524 driver to use.
225
 * @param[in]   reg         Command register to start at.
226
 * @param[out]  data        Pointer to store the group data to.
227
 * @param[in]   length      Number of registers/bytes to read.
228
 * @param[in]   timeout     Timeout for the function to return (in microseconds).
229
 *
230
 * @return    Indicator whether the function call was successful or a timeout occurred.
231
 */
232
inline apalExitStatus_t
233
pcal6524_lld_read_continuous(const PCAL6524Driver* const pcal6524d, const pcal6524_lld_cmd_t reg, uint8_t* const data, const uint8_t length, const apalTime_t timeout)
234
{
235
  apalDbgAssert(pcal6524d != NULL && pcal6524d->i2cd != NULL);
236
  apalDbgAssert(data != NULL);
237
  apalDbgAssert(length <= PCAL6524_LLD_NUM_REGISTERS);
238
239
  uint8_t txbuf = (uint8_t)reg | PCAL6524_LLD_CMD_AUTOINCREMENT;
240
  return apalI2CMasterTransmit(pcal6524d->i2cd, pcal6524d->addr, &txbuf, 1, data, length, timeout);
241
}
242
243
/**
244
 * @brief   Write multiple registers continously, starting at an arbitrary one.
245
 *
246
 * @param[in]   pcal6524d   The PCAL6524 driver to use.
247
 * @param[in]   reg         Command register to start at.
248
 * @param[in]   data        Pointer to the data to write.
249
 * @param[in]   length      Number of registers/bytes to write.
250
 * @param[in]   timeout     Timeout for the function to return (in microseconds).
251
 *
252
 * @return    Indicator whether the function call was successful or a timeout occurred.
253
 */
254
inline apalExitStatus_t
255
pcal6524_lld_write_continuous(const PCAL6524Driver* const pcal6524d, const pcal6524_lld_cmd_t reg, const uint8_t* const data, const uint8_t length, const apalTime_t timeout)
256
{
257
  apalDbgAssert(pcal6524d != NULL && pcal6524d->i2cd != NULL);
258
  apalDbgAssert(data != NULL);
259
  apalDbgAssert(length <= PCAL6524_LLD_NUM_REGISTERS);
260
261
  uint8_t txbuf[PCAL6524_LLD_NUM_REGISTERS + 1] = {(uint8_t)reg | PCAL6524_LLD_CMD_AUTOINCREMENT};
262
  memcpy(&txbuf[1], data, length);
263
  return apalI2CMasterTransmit(pcal6524d->i2cd, pcal6524d->addr, txbuf, length + 1, NULL, 0, timeout);
264
}
265
266
#endif /* defined(AMIROLLD_CFG_USE_PCAL6524) */
267
268
/** @} */