Statistics
| Branch: | Tag: | Revision:

amiro-lld / drivers / PCAL6524 / v1 / alld_PCAL6524.c @ 72369edc

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