This blog is based on real world work. I'm controlling a TI DRV8711 stepper motor controller via SPI.
I need to modify 16-bit registers of that IC. TI provided a header file with register definitions, and code to convert that struct to a 16 bit unsigned integer. That integer can then be sent over SPI.
C code
register struct (TI example: the control register)
// CTRL Register struct CTRL_Register { uint16_t Address; // bits 14-12 uint16_t DTIME; // bits 11-10 uint16_t ISGAIN; // bits 9-8 uint16_t EXSTALL; // bit 7 uint16_t MODE; // bits 6-3 uint16_t RSTEP; // bit 2 uint16_t RDIR; // bit 1 uint16_t ENBL; // bit 0 };
code to convert an instance of the struct (reg) to a 16 bit unsigned int and write to SPI:
uint16_t data; // prepare CTRL Register data = (reg.Address << 12) | (reg.DTIME << 10) | (reg.ISGAIN << 8) |(reg.EXSTALL << 7) | (reg.MODE << 3) | (reg.RSTEP << 2) | (reg.RDIR << 1) | (reg.ENBL); spi_write(data);
C++ code
in C++, we can teach the structure to convert itself to a 16 bit unsigned int (the operator uint16_t() below):
I also encapsulated the address of the register. It's fixed, so your firmware should not have to deal with that.
// CTRL Register struct CTRL_Register { uint16_t DTIME; // bits 11-10 uint16_t ISGAIN; // bits 9-8 uint16_t EXSTALL; // bit 7 uint16_t MODE; // bits 6-3 uint16_t RSTEP; // bit 2 uint16_t RDIR; // bit 1 uint16_t ENBL; // bit 0 inline operator uint16_t() const { return (0x0000 << 12) | (DTIME << 10) | (ISGAIN << 8) |(EXSTALL << 7) | (MODE << 3) | (RSTEP << 2) | (RDIR << 1) | (ENBL); } };
and then write the struct directly to SPI (conversion is done by the struct when being passed to this call - because we trained it how to do that).
spi_write(reg);
Note that there is no conversion in your user code - the struct will do it. We can just pass the struct to the SPI write procedure.
All knowledge on what fields are available in the register, and how to club it into the 16 bits, is contained within the struct.
The code does not add anything to the runtime / firmware. But the register's bit structure knowledge is fully contained within the struct. Your client software doesn't need to shift bits.
Thank you for reading. Critique is welcome.
bonus pub quiz question: why did I put const in the conversion function's declaration?