Skip to content

Commit 3aeb6c4

Browse files
author
harbaum
committed
Finalize drv8908 detection and usage
1 parent 1bd971c commit 3aeb6c4

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

ftduino/libraries/Ftduino/Ftduino.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
293294
void 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)
303305
uint8_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

532629
void Ftduino::motor_set(uint8_t port, uint8_t mode, uint8_t pwm) {

0 commit comments

Comments
 (0)