Created a new IOP16 which adds Jump to Subroutine (JSR) and Return from Subroutine (RTS) opcodes to the IOP16 (in new IOP16B VHDL code). This is a single level only. Implementing nested subroutines would require stack memory and additional resources (another 2 memory blocks). A short LIFO could probably be implemented in logic/registers but isn't worthwhile in this application since a single level is enough.
This allows the in-line I2C functions to be replaced with subroutines and greatly shortens the code length. The code runs slower due to the added burden of the two instructions, but this is not a significant issue since speed it not a particular concern. because the I2C interface runs much slower than the CPU.
This implies the passed parameters need to be placed in specific registers which requires careful control.
Example of writing a value to an I2C register - before the change.
After the change - the calling code is:
The I2C subroutine code is:
- R0 = I2C Slave Address
- R1 = I2C Register number
- R2 = Data to write to the I2C I/F / Data that was read from the I2C I/F (return value from the I2C read subroutine)
- R3 = Scratchpad in routines
- R4 = Bogus write value triggers read transfer
- R7 = I2C Busy Status
- R8 - Hardcoded 0x00 value
- R9 = Hardcoded 0x01 value
- RF = Hardcoded 0xFF value
Code Size Reduction
The code size before the change was 975 lines and 243 lines after creating I2C read/I2C write subroutines (JSR and RTS). That's a 75% reduction in code size.