@@ -320,8 +320,21 @@ namespace pimoroni {
320
320
Pin::adc (1 , 7 , 0 )}
321
321
{}
322
322
323
- bool IOExpander::init (bool skipChipIdCheck) {
324
- bool succeeded = true ;
323
+ bool IOExpander::init (bool skipChipIdCheck, bool perform_reset) {
324
+ if (!skipChipIdCheck) {
325
+ uint16_t chip_id = get_chip_id ();
326
+ if (chip_id != CHIP_ID) {
327
+ if (debug) {
328
+ printf (" Chip ID invalid: %04x expected: %04x\n " , chip_id, CHIP_ID);
329
+ }
330
+ return false ;
331
+ }
332
+ }
333
+
334
+ // Reset the chip if requested, to put it into a known state
335
+ if (perform_reset && !reset ()) {
336
+ return false ;
337
+ }
325
338
326
339
if (interrupt != PIN_UNUSED) {
327
340
gpio_set_function (interrupt, GPIO_FUNC_SIO);
@@ -331,17 +344,36 @@ namespace pimoroni {
331
344
enable_interrupt_out (true );
332
345
}
333
346
334
- if (!skipChipIdCheck) {
335
- uint16_t chip_id = get_chip_id ();
336
- if (chip_id != CHIP_ID) {
337
- if (debug) {
338
- printf (" Chip ID invalid: %04x expected: %04x\n " , chip_id, CHIP_ID);
339
- }
340
- succeeded = false ;
347
+ return true ;
348
+ }
349
+
350
+ uint8_t IOExpander::check_reset () {
351
+ uint8_t user_flash_reg = reg::USER_FLASH;
352
+ uint8_t value;
353
+ if (i2c_write_blocking (i2c->get_i2c (), address, &user_flash_reg, 1 , false ) == PICO_ERROR_GENERIC) {
354
+ return 0x00 ;
355
+ }
356
+ if (i2c_read_blocking (i2c->get_i2c (), address, (uint8_t *)&value, sizeof (uint8_t ), false ) == PICO_ERROR_GENERIC) {
357
+ return 0x00 ;
358
+ }
359
+
360
+ return value;
361
+ }
362
+
363
+ bool IOExpander::reset () {
364
+ uint32_t start_time = millis ();
365
+ set_bits (reg::CTRL, ctrl_mask::RESET);
366
+ // Wait for a register to read its initialised value
367
+ while (check_reset () != 0x78 ) {
368
+ sleep_ms (1 );
369
+ if (millis () - start_time >= RESET_TIMEOUT_MS) {
370
+ if (debug)
371
+ printf (" Timed out waiting for Reset!" );
372
+ return false ;
341
373
}
342
374
}
343
375
344
- return succeeded ;
376
+ return true ;
345
377
}
346
378
347
379
i2c_inst_t * IOExpander::get_i2c () const {
@@ -370,7 +402,7 @@ namespace pimoroni {
370
402
371
403
void IOExpander::set_address (uint8_t address) {
372
404
set_bit (reg::CTRL, 4 );
373
- i2c->reg_write_uint8 (address, reg::ADDR, address);
405
+ i2c->reg_write_uint8 (this -> address , reg::ADDR, address);
374
406
this ->address = address;
375
407
sleep_ms (250 ); // TODO Handle addr change IOError better
376
408
// wait_for_flash()
@@ -491,13 +523,35 @@ namespace pimoroni {
491
523
return divider_good;
492
524
}
493
525
494
- void IOExpander::set_pwm_period (uint16_t value, bool load) {
526
+ void IOExpander::set_pwm_period (uint16_t value, bool load, bool wait_for_load ) {
495
527
value &= 0xffff ;
496
528
i2c->reg_write_uint8 (address, reg::PWMPL, (uint8_t )(value & 0xff ));
497
529
i2c->reg_write_uint8 (address, reg::PWMPH, (uint8_t )(value >> 8 ));
498
530
499
531
if (load)
500
- pwm_load ();
532
+ pwm_load (wait_for_load);
533
+ }
534
+
535
+ uint16_t IOExpander::set_pwm_frequency (float frequency, bool load, bool wait_for_load) {
536
+ uint32_t period = (uint32_t )(CLOCK_FREQ / frequency);
537
+ if (period / 128 > MAX_PERIOD) {
538
+ return MAX_PERIOD;
539
+ }
540
+ if (period < 2 ) {
541
+ return 2 ;
542
+ }
543
+
544
+ uint8_t divider = 1 ;
545
+ while ((period > MAX_PERIOD) && (divider < MAX_DIVIDER)) {
546
+ period >>= 1 ;
547
+ divider <<= 1 ;
548
+ }
549
+
550
+ period = MIN (period, MAX_PERIOD); // Should be unnecessary because of earlier raised errors, but kept in case
551
+ set_pwm_control (divider);
552
+ set_pwm_period ((uint16_t )(period - 1 ), load, wait_for_load);
553
+
554
+ return (uint16_t )period;
501
555
}
502
556
503
557
uint8_t IOExpander::get_mode (uint8_t pin) {
@@ -669,7 +723,7 @@ namespace pimoroni {
669
723
}
670
724
}
671
725
672
- void IOExpander::output (uint8_t pin, uint16_t value, bool load) {
726
+ void IOExpander::output (uint8_t pin, uint16_t value, bool load, bool wait_for_load ) {
673
727
if (pin < 1 || pin > NUM_PINS) {
674
728
printf (" Pin should be in range 1-14." );
675
729
return ;
@@ -685,7 +739,7 @@ namespace pimoroni {
685
739
i2c->reg_write_uint8 (address, io_pin.reg_pwml , (uint8_t )(value & 0xff ));
686
740
i2c->reg_write_uint8 (address, io_pin.reg_pwmh , (uint8_t )(value >> 8 ));
687
741
if (load)
688
- pwm_load ();
742
+ pwm_load (wait_for_load );
689
743
}
690
744
else {
691
745
if (value == LOW) {
0 commit comments