3. Low-Level SPI Commands

3.a. Motor Commands
3.a.01. Command 214: Set Motor Mode
3.a.02. Command 128: Independent Motor Brake (inB = inA)
3.a.03. Command 136: Independent Motor Drive (inB = ~inA)
3.a.04. Command 232: Independent Motor Drive with Acceleration (inB = ~inA)
3.a.05. Command 144: Joint Motor Operation (inA1 = inB1 = in1; inA2 = inB2 = in2)
3.a.06. Command 228: Joint Motor Drive with Acceleration (in2 = ~in1)
3.a.07. Command 208: Set Acceleration
3.a.08. Command 188: Set Brake Duration
3.a.09. Command 212: Set Number of Current Sense Samples in Averages
3.a.10. Command 192: Set Current Limit
3.a.11. Command 210: Set Motor PWM Frequencies
3.a.12. Command 216: Get Average Motor Current
3.b. Buzzer Commands
3.b.1. Command 152: Play Note
3.b.2. Command 160: Play Frequency
3.b.3. Command 176: Play Melody
3.b.4. Command 168: Store Note
3.b.5. Command 224: End Melody
3.b.6. Command 186: Erase Melodies
3.b.7. Command 226: Set Volume
3.b.8. Command 187: Set Note Gap
3.b.9. Command 225: Buzzer Off
3.c. UART Commands
3.c.01. Command 200: Set Serial Parameters
3.c.02. Command 219: Read UART Byte
3.c.03. Command 220: Send UART Byte
3.c.04. Command 222: Get Free Space in Send Buffer
3.c.05. Command 223: Get Number of Bytes in Read Buffer
3.c.06. Command 227: Set Read Ready Size
3.c.07. Command 252: Get UART Error
3.d. Miscellaneous Commands
3.d.01. Command 218: Get Status
3.d.02. Command 240: Write to EEPROM
3.d.03. Command 248: Read from EEPROM
3.d.04. Command 254: Check If EEPROM Is Busy
3.d.05. Command 253: Get Firmware version (version = major byte . minor byte)
3.d.06. Command 255: NULL Command

We will now elaborate on the low-level SPI commands.

Some commands produce immediate results (e.g. non-acceleration motor commands, all the read commands, buzzer off) independent of the state of the mega168’s main loop. Others queue up actions to be carried out by the appropriate handler in the mega168’s main loop (e.g. UART transmit, most buzzer commands, acceleration motor commands).

The SPI clock can run at up to 2.5 MHz, which corresponds to SPI byte rate of approximately 312 kHz. The mega168 is designed to be able to accept these bytes as quickly as you are able to send them without losing data or ignoring commands. However there are a few exceptions:

  • If you are sending a command that will cause the mega168 to write to its EEPROM, you will be tying up the mega168’s main loop for approximately 3.4 ms per EEPROM write. You should not send another command that will cause an EEPROM write until after the previous write has finished. For example, do not stream “Store Note” commands to the mega168 any faster than one packet per 10.2 ms. You can send a command packet that does not cause an EEPROM write immediately following one that does, but realize that the various handlers in the mega168’s main loop will not get around to that command until after the EEPROM writes are finished. As such, we recommend that, if possible, you have the mega168 perform any necessary EEPROM writes during the initialization phase of your program rather than in the middle of some crucial, time-sensitive phase.
  • If you are sending a read command, you must give the mega168 time to load the desired value into its SPI data register before initiating the SPI transmission that will transfer it to the mega644. The recommended protocol is to transmit the byte that will tell the mega168 what value is desired (usually this is just the command byte), wait for the transmission to complete, then wait for an additional 3us before transmitting another byte (usually this will be a junk data byte or a NULL command). As this last byte is transmitted over the SPI to the mega168, the desired value is transmitted over the SPI to the mega644. When transmission of this last byte is complete, the mega644’s SPI data register, SPDR, holds the requested value.
  • It doesn’t make sense to stream some commands as quickly as possible to the mega168. For example, you can send PWM updates to the mega168 at 143 kHz, but given that the fastest PWM frequency you can use is ~20 kHz, such an update rate would be pointless.

In general, you rarely need to worry about having to insert delays between the bytes you’re transmitting over the SPI; it is up to you to decide what update rate makes the most sense for your particular application.

Note: “motor 1” corresponds to motor bit 0 and “motor 2” corresponds to motor bit 1.