While I've been focusing on the desktop application, hardware has begun to arrive and I've started hooking things up and writing code. Since I wrote an emulator to be able to test the desktop application, I was able to port large chunks of python emulator code to C++ code for the Teensy.
One of the challenges I faced was the size of the EEPROM on the MCU. It's only 2KB and I had to fit the entire user configuration into it. This meant I had to be clever with bit packing, but it also meant I had to cut down on some of the features I wanted. For example, the device has 4 lookup tables that can be used to transform output values. Initially, each of those tables held 16 entries, each one consisting of 2, 32 bit floating point numbers, in addition to the table name (16 bytes). That alone is 576 bytes of data, or about 25% of available space. I decided to half the table entries to only 8. There were other sacrifices too, mainly in how many bits I use for some settings, which limited the possible values for those settings. When I was all done squeezing, I was using 2024 bytes, just under the 2048 byte limit.
But I wasn't happy making those compromises. I started considering adding an external EEPROM to the parts list and even ordered some chips. But as cheap as that might be, it wasn't sitting well. Then I happened across some posts on the Teensy forum about using flash memory for data storage. The MCU I'm using has lots of flash, 256KB to be exact. My compiled code was coming in much smaller than that, so there was a bunch of unused flash on the chip. It turns out using that flash for data is tricky. For example, you can't write to it from code running in flash (i.e., the firmware that needs to use the flash). You have to write code to RAM and run it, which disables program execution in flash while the writing is happening. Needless to say, there's no standard library for this, but with the aid of information found in the forums and banging my head on my desk, I was eventually able to successfully write and read flash data. I carved out 16KB of flash for configuration data, 8 times as much EEPROM, and I still have plenty of space for code and even more data, if necessary.
With the space constraint removed, I put back all the configuration data I removed before and added a little more to help clean some things up. Working with tightly bit packed data is hard and sacrifices code clarity for data space, so undoing some of those machinations allowed the code to read more cleanly.
With the new breathing room, I was also able to consider one of my other desired features, CAN output. I haven't added that to the firmware or desktop app yet, but I will soon. The idea is to allow the user to configure some number of CAN messages (message ID and data bytes) to be sent to the CAN bus at regular intervals. While I don't have a need for something like that, it has been mentioned in some forum discussions as a desirable feature. It would allow a user who knew what secret messages could be sent to request data from a vehicle's ECU that isn't written to the CAN bus normally. For example, apparently you can query some vehicles for oxygen sensor readings which might be useful for engine tuning or throttle mapping.