@@ -290,6 +290,7 @@ void Ftduino::spi_interrupt_exec()
290290}
291291#endif
292292
293+ #if defined(OUTPUT_DRIVER_AUTO) || defined(OUTPUT_DRIVER_MC33879A) || defined(OUTPUT_DRIVER_TLE94108EL)
293294void Ftduino::spi_interrupt () {
294295 // Use chip specific handler routine
295296#if defined(OUTPUT_DRIVER_AUTO)
@@ -298,6 +299,7 @@ void Ftduino::spi_interrupt() {
298299 ftduino.spi_interrupt_exec ();
299300#endif
300301}
302+ #endif
301303
302304#if defined(OUTPUT_DRIVER_AUTO)
303305uint8_t Ftduino::spi_probe () {
@@ -437,7 +439,72 @@ void Ftduino::output_init() {
437439 SPDR = 0x00 ;
438440 }
439441#endif
442+
443+ // since the drv8908 is able to do all PWM for all eight channels in hardware we
444+ // need to setup its hardware accordingly
445+ #if defined(OUTPUT_DRIVER_AUTO)
446+ if (driver_chip == CHIP_DRV8908)
447+ #endif
448+ #if defined(OUTPUT_DRIVER_AUTO) || defined(OUTPUT_DRIVER_DRV8908)
449+ {
450+ // give chip a millisecond to come out of reset/sleep
451+ delay (1 );
452+
453+ drv8908_transfer_byte (PWM_CTRL_1, 0xff ); // set all pwm modes
454+ drv8908_transfer_byte (PWM_CTRL_2, 0x00 ); // enable all PWM generators
455+ drv8908_transfer_byte (SR_CTRL_1, 0x00 ); // slew rate 0.6V/us
456+
457+ drv8908_transfer_byte (OLD_CTRL_1, 0xff ); // disable open load detection
458+ drv8908_transfer_byte (OLD_CTRL_2, 0xc0 ); // don't disable outputs on open load detection
459+ drv8908_transfer_byte (OLD_CTRL_3, 0x00 );
460+ drv8908_transfer_byte (OLD_CTRL_4, 0x00 ); // disable low current open load detection
461+ drv8908_transfer_byte (OLD_CTRL_5, 0x00 ); // disable passive current open load detection
462+ drv8908_transfer_byte (OLD_CTRL_6, 0x00 );
463+
464+ // map all pwm channels 1-8 to outputs O1-O8
465+ drv8908_transfer_byte (PWM_MAP_CTRL_1, 0b00001000 );
466+ drv8908_transfer_byte (PWM_MAP_CTRL_2, 0b00011010 );
467+ drv8908_transfer_byte (PWM_MAP_CTRL_3, 0b00101100 );
468+ drv8908_transfer_byte (PWM_MAP_CTRL_4, 0b00111110 );
469+
470+ // set all pwm frequencies to 200Hz
471+ drv8908_transfer_byte (PWM_FREQ_CTRL_1, 0xaa );
472+ drv8908_transfer_byte (PWM_FREQ_CTRL_2, 0xaa );
473+ }
474+ #endif
475+ }
476+
477+ #if defined(OUTPUT_DRIVER_AUTO) || defined(OUTPUT_DRIVER_DRV8908)
478+ uint8_t Ftduino::drv8908_transfer_byte (uint8_t addr, uint8_t value) {
479+ PORTB &= ~(1 <<0 ); // activate /SS
480+ _delay_us (1 );
481+ SPDR = addr; while (!(SPSR & (1 <<SPIF))); // wait for SPI transfer to end
482+ uint8_t status = SPDR;
483+ SPDR = value; while (!(SPSR & (1 <<SPIF))); // wait for SPI transfer to end
484+ uint8_t retval = SPDR;
485+ PORTB |= (1 <<0 ); // drive /SS high
486+
487+ // status byte: 1 1 OT OLD OCP UVLO OVP NPOR
488+ // OT = Overtemperature
489+ // OLD = Open Load Detected
490+ // OCP = Overcurrent Protection
491+ // UVLO = Undervoltage
492+ // OVP = Overvoltage
493+ // NPOR = Not Power-On Reset
494+
495+ // clear any error
496+ if (status != 0xc1 ) {
497+ _delay_us (10 );
498+ PORTB &= ~(1 <<0 ); // activate /SS
499+ _delay_us (1 );
500+ SPDR = CONFIG_CTRL; while (!(SPSR & (1 <<SPIF))); // write CONFIG_CTRL and wait for SPI transfer to end
501+ SPDR = 0x01 ; while (!(SPSR & (1 <<SPIF))); // clear all faults and wait for SPI transfer to end
502+ PORTB |= (1 <<0 ); // drive /SS high
503+ }
504+
505+ return retval;
440506}
507+ #endif
441508
442509#if defined(OUTPUT_DRIVER_AUTO) || defined(OUTPUT_DRIVER_MC33879A)
443510#define MC33879_PORT (a ) (1 <<(a-1 ))
@@ -516,6 +583,35 @@ void Ftduino::output_set(uint8_t port, uint8_t mode, uint8_t pwm) {
516583 }
517584#endif
518585
586+ #if defined(OUTPUT_DRIVER_AUTO) || defined(OUTPUT_DRIVER_DRV8908)
587+ #if defined(OUTPUT_DRIVER_AUTO)
588+ if (driver_chip == CHIP_DRV8908)
589+ #endif
590+ {
591+ uint8_t op_ctrl = (port<=3 )?OP_CTRL_1:OP_CTRL_2;
592+ uint8_t op_port = port & 3 ; // 0..3
593+ uint8_t op_mode = (mode==0 )?0 :((mode==1 )?2 :1 );
594+
595+ // expand duty cycle to 8 bits, so that 00000000 and 11111111 are reached
596+ drv8908_transfer_byte (PWM_DUTY_CTRL_1+port, (pwm<<2 )|(pwm&3 )); // set duty cycle
597+
598+ // set output mode, ftduino os off=0, hi=1, low=2, drv is off,low,hi
599+ uint8_t tmp = drv8908_transfer_byte (0x40 | op_ctrl, 0 ); // 0x40 = read flag
600+ tmp &= ~(3 << (2 *op_port));
601+ tmp |= op_mode << (2 *op_port);
602+ drv8908_transfer_byte (op_ctrl, tmp);
603+
604+ // self.set(output, mode)
605+ // self.enable_pwm(output, True)
606+ // self.map_pwm(output, output) # use pwm ch 1 for O1, ch 2 for O2, ...
607+ // self.set_pwm_freq(output, DRV8908.FREQ_200HZ) # 200Hz is fine for motors and lamps
608+ // self.set_pwm_duty(output, value)
609+ }
610+ #endif
611+
612+ #if defined(OUTPUT_DRIVER_AUTO) || defined(OUTPUT_DRIVER_MC33879A) || defined(OUTPUT_DRIVER_TLE94108EL)
613+ // the DRV8908 is the only chip that does not need the spi pwm table
614+
519615// Serial.print("SET/CLR "); Serial.print(set_mask, HEX); Serial.print(" "); Serial.println(clr_mask, HEX);
520616// Serial.print("STATE "); Serial.println(spi_state, HEX);
521617
@@ -527,6 +623,7 @@ void Ftduino::output_set(uint8_t port, uint8_t mode, uint8_t pwm) {
527623 } else
528624 spi_tx_in[i] &= ~(set_mask | clr_mask);
529625 }
626+ #endif
530627}
531628
532629void Ftduino::motor_set (uint8_t port, uint8_t mode, uint8_t pwm) {
0 commit comments