Part Number: DRV10983-Q1
I can read any register I want, EEPROM or otherwise. I can write to the control register for 0xC0DE and read it back. I can set the status register to enable mass write. When I try to write to 0x90, it sends a NACK in response. When I try to set the status register to individual access mode, it sends a NACK in response. If I try to re-send my commands in response to these NACKs, it keeps NACKing. I'm programming it via an MSP430F2618 that's supposed to eventually control it, and it's all soldered together at this point.
code in case that helps.
void write_eeprom(){
//I found two different methods to do this, so as long as there's no directly conflicting information, I'm choosing the most cautious blend of both methods.
//One conflict found: One says to wait for eeReadyStatus = 1 before you do anything else, the other says only wait for eeReadyStatus just before the CONFIG1-7 write.
//Chosen solution: Wait, then write, then wait again, with a loop counter on the first wait that breaks out within like 10 loops in case that's actually just wrong.
//Wait for eeReadyStatus, but only give it 3 tries before we try to move on
uint16_t eeReadyStatus = 0;
uint8_t loop_counter = 3; //Currently only waiting 3 times max, since we've got another wait loop later in the code.
while((eeReadyStatus == 0) && (loop_counter != 0)){
loop_counter--;
delay_ms(10); //Honestly, by the time we get to this line of code the device has probably been on for more than 10ms already, but whatever.
drv_read(DRV_EEPROM2_REG_ADDR, &eeReadyStatus);
//Yes I should maybe use my bits_from_range function but honestly it's just bit 0.
eeReadyStatus &= BIT0; //0x32[0]
}
//Set MTR_DIS =1 to disable the motor driver DRV_EECTRL_REG_ADDR[15]
uint16_t eepByte = 0;
drv_read(DRV_EECTRL_REG_ADDR, &eepByte);
eepByte |= BITF; //And set the only bit I actually care about.
drv_write(DRV_EECTRL_REG_ADDR, eepByte);
//Clear DRV_EEPROM1_REG_ADDR
drv_write(DRV_EEPROM1_REG_ADDR, 0x0000);
//Then we have to write 0xC0DE to DRV_EEPROM1_REG_ADDR
drv_write(DRV_EEPROM1_REG_ADDR, 0xC0DE);
/*~~~~~~~Shenanigans Test~~~~~~~~~~~
//This assumes you already did the safety checks and whatnot.
//we want... 0b(000)(0)(000)(0)(00000)(1)(10)
//for (res)(sren)(res)(er)(res)(ewren)(eam)
//Maybe the reserved bits are throwing me off.
drv_read(DRV_EEPROM5_REG_ADDR, &eepByte);
eepByte |= (BIT1 | BIT2);
drv_write(DRV_EEPROM5_REG_ADDR, eepByte);
//~~~~~~End Shenanigans Test~~~~~~~~~~~~~
*/
//Then we double check eeReadyStatus
//Do we want to clear eeReadyStatus before this to force the check?
//This one doesn't get a loop counter because we actually don't want to go until it's ready
//Though, TODO: add an error out response after some number of loops.
eeReadyStatus = 0;
while(eeReadyStatus == 0){
drv_read(DRV_EEPROM2_REG_ADDR, &eeReadyStatus);
//Yes I should maybe use my bits_from_range function but honestly it's just bit 0.
eeReadyStatus &= BIT0; //0x32[0]
if (eeReadyStatus == 0){
delay_ms(10);
}
}
delay_ms(500);
//Then we write the CONFIG1-7 data
//Current config source: LatestQ1Settings.csv
drv_write(DRV_CONFIG1_REG_ADDR, 0x0079); //DRV10983Q1 0x90 0x79
delay_ms(10);
drv_write(DRV_CONFIG2_REG_ADDR, 0x1A3F); //DRV10983Q1 0x91 0x1A3F
delay_ms(10);
drv_write(DRV_CONFIG3_REG_ADDR, 0x1800); //DRV10983Q1 0x92 0x1800
delay_ms(10);
drv_write(DRV_CONFIG4_REG_ADDR, 0x008F); //DRV10983Q1 0x93 0x8F
delay_ms(10);
drv_write(DRV_CONFIG5_REG_ADDR, 0x3B80); //DRV10983Q1 0x94 0x3B80
delay_ms(10);
drv_write(DRV_CONFIG6_REG_ADDR, 0x3C40); //DRV10983Q1 0x95 0x3C40
delay_ms(10);
drv_write(DRV_CONFIG7_REG_ADDR, 0x002B); //DRV10983Q1 0x96 0x2B
delay_ms(10);
//we want... 0b(000)(0)(000)(0)(00000)(1)(10)
//for (res)(sren)(res)(er)(res)(ewren)(eam)
//which ends up being 0x00 and 0x06
drv_read(DRV_EEPROM5_REG_ADDR, &eepByte);
eepByte |= (BIT1 | BIT2);
drv_write(DRV_EEPROM5_REG_ADDR, eepByte);
//This one doesn't get a loop counter because we actually don't want to go until it's ready.
//Though we do clear eeReadyStatus
eeReadyStatus = 0;
//Though, TODO: add an error out response after some number of loops.
//Also, yes both versions agree that this goes before the MTR_DIS re-enable
while(eeReadyStatus == 0){
drv_read(DRV_EEPROM2_REG_ADDR, &eeReadyStatus);
//Yes I should maybe use my bits_from_range function but honestly it's just bit 0.
eeReadyStatus &= BIT0; //0x32[0]
if (eeReadyStatus == 0){
delay_ms(10);
}
}
//Re-enable MTR_DIS = 0 DRV_EECTRL_REG_ADDR[15]
//Now, that bit is write only, and the rest are read only.
//But, I2C is byte by byte, not bit by bit.
//Furthermore, I don't know what happens when you only access one byte of a register that holds two bytes
//Or what happens when you try to write to a read-only register
//Or what happens when you try to write to a read-only register it tells you not to even access
eepByte = 0;
drv_read(DRV_EECTRL_REG_ADDR, &eepByte); //So, I'm going to read both bytes, in case I2C would get mad if I didn't access them both.
//Possible failure mode: bit 15 is "write only" and the rest are labeled readable but "do not access"
eepByte &= ~BITF; //And set the only bit I actually care about.
drv_write(DRV_EECTRL_REG_ADDR, eepByte); //And write to both bytes, figuring that either they're properly write protected and it won't matter.
//Or they're not actually write protected and I'm avoiding breaking something esoteric.
//If that doesn't work, replace the i2c writes to config1-7 with this:
//put reg_addr in 0x33 (eeprom programming3 register)
//put the data in 0x34 (eeprom programming4 register)
//Which is the the way it works in individual access mode.
}