24#if (BOARD_MC33972_COUNT > 0)
35#define DRIVER_NAME "mc33972"
48#define CMD(cmd, data) (((cmd) << 16) | ((data) << 0))
50#define CMD_STATUS CMD(0x00, 0x00)
51#define CMD_SETTINGS(mask) CMD(0x01, (mask))
52#define CMD_WAKEUPEN(i, mask) CMD(0x02 + (i), (mask))
53#define CMD_METALLIC(i, mask) CMD(0x04 + (i), (mask))
54#define CMD_ANALOG(curr, ch) CMD(0x06, (((curr) & 0x3) << 5) | (((ch) & 0x1f) << 0))
55#define CMD_WETTING_TMR(i, mask) CMD(0x07 + (i), (mask))
56#define CMD_TRI_STATE(i, mask) CMD(0x09 + (i), (mask))
57#define CMD_CALIB CMD(0x0b, 0x00)
58#define CMD_SLEEP(int_t, scan_t) CMD(0x0c, (((int_t) & 0x7) << 3) | (((scan_t) & 0x7) << 0))
59#define CMD_RST CMD(0x7f, 0x00)
62#define SP_PINS_MASK 0x00ff
63#define SP_PINS_EXTRACT(pins) (((pins) >> 14) & SP_PINS_MASK)
65#define SG_PINS_MASK 0x3fff
66#define SG_PINS_EXTRACT(pins) (((pins) >> 0) & SG_PINS_MASK)
69#define FLAG_THERM (1 << 23)
70#define FLAG_INT (1 << 22)
72#define PIN_MASK(pin) (BIT(pin))
101 int spi_w(uint32_t tx);
124static Mc33972
chips[BOARD_MC33972_COUNT];
137int Mc33972::spi_w(uint32_t tx)
142 SPIDriver *spi = cfg->spi_bus;
144 txb[0] = (tx >> 16) & 0xff;
145 txb[1] = (tx >> 8) & 0xff;
146 txb[2] = (tx >> 0) & 0xff;
150 spiStart(spi, &cfg->spi_config);
154 for (i = 0; i < 3; i++)
155 rxb[i] = spiPolledExchange(spi, txb[i]);
162 i_state = (rxb[0] << 16) | (rxb[1] << 8) | (rxb[2] << 0);
173int Mc33972::update_status()
175 return spi_w(CMD_STATUS);
178int Mc33972::update_pullups()
183 ret = spi_w(CMD_TRI_STATE(SP_BANK, SP_PINS_EXTRACT(~en_pins)));
186 ret = spi_w(CMD_TRI_STATE(SG_BANK, SG_PINS_EXTRACT(~en_pins)));
191int Mc33972::comm_test()
201 for (
int i = 0; i < MC33972_INPUTS; i++) {
203 ret = spi_w(CMD_ANALOG(0, i + 1));
206 ret = update_status();
210 if (i_state & PIN_MASK(i))
223int Mc33972::chip_init()
228 ret = spi_w(CMD_RST);
233 chThdSleepMilliseconds(3);
252 ret = update_pullups();
257 ret = spi_w(CMD_METALLIC(SP_BANK, 0));
260 ret = spi_w(CMD_METALLIC(SG_BANK, 0));
272void Mc33972::wake_driver()
275 chibios_rt::CriticalSectionLocker csl;
278 if (!port_is_isr_context()) {
294 Mc33972 *chip =
reinterpret_cast<Mc33972*
>(p);
296 chRegSetThreadName(DRIVER_NAME);
300 ret = chip->chip_init();
302 chThdSleepMilliseconds(1000);
310 msg_t msg = chSemWaitTimeout(&chip->wake, TIME_MS2I(MC33972_POLL_INTERVAL_MS));
312 if ((chip->cfg == NULL) ||
317 if (msg == MSG_TIMEOUT) {
319 ret = chip->update_status();
323 ret = chip->update_pullups();
342int Mc33972::setPadMode(
size_t pin,
iomode_t mode) {
343 if (
pin >= MC33972_INPUTS)
355 en_pins |= PIN_MASK(
pin);
363int Mc33972::readPad(
size_t pin) {
364 if (
pin >= MC33972_INPUTS)
368 return !!(i_state & PIN_MASK(
pin));
374 if (
pin >= MC33972_INPUTS)
378 if (i_state & FLAG_THERM)
379 diag = PIN_DRIVER_OVERTEMP;
390 chSemObjectInit(&wake, 0);
393 thread = chThdCreateStatic(thread_wa,
sizeof(thread_wa),
394 PRIO_GPIOCHIP, mc33972_driver_thread,
this);
404 chThdTerminate(thread);
417 if ((!cfg) || (!cfg->
spi_bus) || (index >= BOARD_MC33972_COUNT))
426 Mc33972& chip =
chips[index];
429 if (chip.cfg != NULL)
444 (void)base; (void)index; (void)cfg;
int gpiochip_register(brain_pin_e base, const char *name, GpioChip &gpioChip, size_t size)
Register gpiochip.
uint32_t iomode_t
Digital I/O modes.
static THD_FUNCTION(mc33972_driver_thread, p)
static Mc33972 chips[BOARD_MC33972_COUNT]
int mc33972_add(brain_pin_e base, unsigned int index, const struct mc33972_config *cfg)
MC33972 driver add.
static THD_WORKING_AREA(storageManagerThreadStack, 3 *UTILITY_THREAD_STACK_SIZE)
virtual brain_pin_diag_e getDiag(size_t)
virtual int readPad(size_t)
virtual int setPadMode(size_t, iomode_t)