@@ -382,9 +382,7 @@ drvBase *CreateI2CDriverByName(const char *driver_name, TwoWire *i2c,
382382I2cController::I2cController () {
383383 _i2c_bus_alt = nullptr ;
384384 _i2c_model = new I2cModel ();
385- // Initialize the default I2C bus
386385 _i2c_bus_default = new I2cHardware ();
387- _i2c_bus_default->InitBus (true );
388386}
389387
390388/* **********************************************************************/
@@ -400,6 +398,28 @@ I2cController::~I2cController() {
400398 delete _i2c_bus_default;
401399}
402400
401+ /* **********************************************************************/
402+ /* !
403+ @brief Removes an I2C driver from the controller and frees memory
404+ @param address
405+ The desired I2C device's address.
406+ */
407+ /* **********************************************************************/
408+ bool I2cController::RemoveDriver (uint32_t address) {
409+ for (drvBase* driver : _i2c_drivers) {
410+ if (driver == nullptr )
411+ continue ;
412+
413+ if (driver->GetAddress () != address)
414+ continue ;
415+
416+ delete driver;
417+ _i2c_drivers.erase (std::find (_i2c_drivers.begin (), _i2c_drivers.end (), driver));
418+ return true ;
419+ }
420+ return false ;
421+ }
422+
403423/* ************************************************************************/
404424/* !
405425 @brief Returns if the I2C bus has been created successfully.
@@ -472,7 +492,40 @@ bool I2cController::Handle_I2cDeviceRemove(pb_istream_t *stream) {
472492 }
473493
474494 // TODO [Online]: Implement the rest of this function
475- WS_DEBUG_PRINTLN (" [i2c] I2cDeviceRemove message not yet implemented!" );
495+ // TODO: Remember - can be on either bus! (default or alt)
496+ // TODO: Remember to handle removal of a mux device or a device on a mux
497+ // strlen(descriptor.i2c_bus_sda) == 0
498+
499+ wippersnapper_i2c_I2cDeviceRemove *msgRemove =
500+ _i2c_model->GetI2cDeviceRemoveMsg ();
501+ if (!msgRemove->has_i2c_device_description ) {
502+ WS_DEBUG_PRINTLN (" [i2c] ERROR: I2cDeviceRemove message missing required "
503+ " device description!" );
504+ return false ;
505+ }
506+
507+ // Check for default bus
508+ if (strlen (msgRemove->i2c_device_description .i2c_bus_scl ) == 0 &&
509+ strlen (msgRemove->i2c_device_description .i2c_bus_sda ) == 0 ) {
510+ WS_DEBUG_PRINTLN (" [i2c] Removing device from default bus..." );
511+ if (!_i2c_bus_default->HasMux ()) {
512+ // TODO: Implement remove, straightforward
513+ if (!RemoveDriver (msgRemove->i2c_device_description .i2c_device_address )) {
514+ WS_DEBUG_PRINTLN (" [i2c] ERROR: Failed to remove i2c device from default bus!" );
515+ return false ;
516+ }
517+ } else {
518+ // Bus has a I2C MUX attached
519+ // Case 1: Is the I2C device connected to a MUX?
520+ if (msgRemove->i2c_device_description .i2c_mux_address != 0xFFFF && msgRemove->i2c_device_description .i2c_mux_channel >= 0 ) {
521+ // TODO: Remove the device from the mux's channel and delete the driver
522+ }
523+ // Case 2: Is the I2C device a MUX?
524+ if (msgRemove->i2c_device_description .i2c_device_address == msgRemove->i2c_device_description .i2c_mux_address ) {
525+ // TODO: Remove the MUX from the i2c bus
526+ }
527+ }
528+ }
476529
477530 return true ;
478531}
@@ -531,18 +584,13 @@ bool I2cController::Handle_I2cBusScan(pb_istream_t *stream) {
531584 _i2c_model->ClearI2cBusScanned ();
532585 wippersnapper_i2c_I2cBusScanned *scan_results =
533586 _i2c_model->GetI2cBusScannedMsg ();
534- bool scan_success = false ;
535-
536- // TODO: Refactor, case 1 and case 2 are functionally VERY similar - can be
537- // combined
538587
588+ bool scan_success = true ;
539589 // Case 1: Scan the default I2C bus
540590 if (_i2c_model->GetI2cBusScanMsg ()->scan_default_bus ) {
541591 // Was the default bus initialized correctly and ready to scan?
542592 if (IsBusStatusOK ()) {
543- if (_i2c_bus_default->ScanBus (scan_results)) {
544- scan_success = true ;
545- } else {
593+ if (!_i2c_bus_default->ScanBus (scan_results)) {
546594 WS_DEBUG_PRINTLN (" [i2c] ERROR: Failed to scan default I2C bus!" );
547595 scan_success = false ;
548596 }
@@ -551,51 +599,69 @@ bool I2cController::Handle_I2cBusScan(pb_istream_t *stream) {
551599 " reset the board!" );
552600 scan_success = false ;
553601 }
554- if (scan_success) {
555- WS_DEBUG_PRINTLN (" [i2c] Scanned default I2C bus successfully!" );
556- }
557- // TODO: Print out what was scanned? or do this at the end
558602 }
559603
560604 // Case 2: Optionally scan the alternative I2C bus
561605 if (_i2c_model->GetI2cBusScanMsg ()->scan_alt_bus ) {
562606 // Is the alt bus initialized?
563607 if (_i2c_bus_alt == nullptr ) {
564- WS_DEBUG_PRINTLN (" [i2c] Initializing alt. i2c bus..." );
565- _i2c_bus_alt = new I2cHardware ();
566- _i2c_bus_alt->InitBus (
567- false ,
608+ _i2c_bus_alt = new I2cHardware (
568609 _i2c_model->GetI2cBusScanMsg ()->i2c_alt_bus_descriptor .i2c_bus_sda ,
569610 _i2c_model->GetI2cBusScanMsg ()->i2c_alt_bus_descriptor .i2c_bus_sda );
570- }
571- // Was the default bus initialized correctly and ready to scan?
572- if (IsBusStatusOK (true )) {
573- if (_i2c_bus_alt->ScanBus (scan_results)) {
574- scan_success = true ;
611+ // Was the default bus initialized correctly and ready to scan?
612+ if (IsBusStatusOK (true )) {
613+ if (!_i2c_bus_alt->ScanBus (scan_results)) {
614+ WS_DEBUG_PRINTLN (" [i2c] ERROR: Failed to scan alt. I2C bus!" );
615+ scan_success = false ;
616+ }
575617 } else {
576- WS_DEBUG_PRINTLN (" [i2c] ERROR: Failed to scan alt. I2C bus!" );
618+ WS_DEBUG_PRINTLN (" [i2c] ERROR: alt. I2C bus state is stuck, please "
619+ " reset the board!" );
577620 scan_success = false ;
578621 }
579- } else {
580- WS_DEBUG_PRINTLN (" [i2c] ERROR: alt. I2C bus state is stuck, please "
581- " reset the board!" );
582- scan_success = false ;
583622 }
584- if (scan_success) {
585- WS_DEBUG_PRINTLN (" [i2c] Scanned alt. I2C bus successfully!" );
623+ }
624+
625+ // Case 3: Optionally scan MUX attached to the default bus
626+ if (_i2c_model->GetI2cBusScanMsg ()->scan_default_bus_mux ) {
627+ if (_i2c_bus_default->HasMux ()) {
628+ if (!_i2c_bus_default->ScanMux (scan_results)) {
629+ WS_DEBUG_PRINTLN (" [i2c] ERROR: Failed to scan I2C MUX on default bus!" );
630+ scan_success = false ;
631+ }
586632 }
587- // TODO: Print out what was scanned? or do this at the end
588633 }
589634
590- // Case 3: Optionally scan MUXes attached to I2C buses
591- if (_i2c_model->GetI2cBusScanMsg ()->i2c_mux_descriptors_count > 0 ) {
592- // Iterate through the MUX descriptors, scanning each MUX
593- for (int i = 0 ; i < _i2c_model->GetI2cBusScanMsg ()->i2c_mux_descriptors_count ; i++) {
594- // []
635+ // Case 4: Optionally scan MUX attached to the alt. bus
636+ if (_i2c_model->GetI2cBusScanMsg ()->scan_alt_bus ) {
637+ if (_i2c_bus_alt->HasMux ()) {
638+ if (!_i2c_bus_alt->ScanMux (scan_results)) {
639+ WS_DEBUG_PRINTLN (" [i2c] ERROR: Failed to scan I2C MUX on alt. bus!" );
640+ scan_success = false ;
641+ }
595642 }
596643 }
597644
645+ // Printout content of scan_results
646+ WS_DEBUG_PRINT (" [i2c] Scan found " );
647+ WS_DEBUG_PRINT (scan_results->i2c_bus_found_devices_count );
648+ WS_DEBUG_PRINTLN (" devices." );
649+ for (int i = 0 ; i < scan_results->i2c_bus_found_devices_count ; i++) {
650+ WS_DEBUG_PRINTLN (i);
651+ WS_DEBUG_PRINT (" Address: " );
652+ WS_DEBUG_PRINTLN (scan_results->i2c_bus_found_devices [i].i2c_device_address ,
653+ HEX);
654+ WS_DEBUG_PRINT (" SCL: " );
655+ WS_DEBUG_PRINTLN (scan_results->i2c_bus_found_devices [i].i2c_bus_scl );
656+ WS_DEBUG_PRINT (" SDA: " );
657+ WS_DEBUG_PRINTLN (scan_results->i2c_bus_found_devices [i].i2c_bus_sda );
658+ WS_DEBUG_PRINT (" MUX Address: " );
659+ WS_DEBUG_PRINTLN (scan_results->i2c_bus_found_devices [i].i2c_mux_address );
660+ WS_DEBUG_PRINT (" MUX Channel: " );
661+ WS_DEBUG_PRINTLN (scan_results->i2c_bus_found_devices [i].i2c_mux_channel );
662+ }
598663
664+ // TODO: Encode and publish out to IO!
599665 // TODO: Take scan_success into account here
600666 return true ;
601667}
@@ -637,9 +703,8 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) {
637703 WS_DEBUG_PRINTLN (" [i2c] Non-default I2C bus specified!" );
638704 if (_i2c_bus_alt == nullptr ) {
639705 WS_DEBUG_PRINTLN (" [i2c] Initializing alternative i2c bus..." );
640- _i2c_bus_alt = new I2cHardware ();
641- _i2c_bus_alt->InitBus (false , device_descriptor.i2c_bus_sda ,
642- device_descriptor.i2c_bus_scl );
706+ _i2c_bus_alt = new I2cHardware (device_descriptor.i2c_bus_sda ,
707+ device_descriptor.i2c_bus_scl );
643708 }
644709 use_alt_bus = true ;
645710 }
0 commit comments