Misc output related subpage of GenBoard/UnderDevelopment/FirmWare
Problems to solve
- free some SRAM ASAP
- fastest and most efficient method is to rip 1000 bytes of table-data from SRAM, and use directly from EEPROM
- to allow a second config page
- although first page still has variable to free up
- for bigger tables (there is no technical reason, but users who don't understand the injopen and alike think very simply: "more is better")
- dynamic config: GenBoard/UnderDevelopment/FirmWare/DynamicConfigRelated
- this will be nice, but to free space, see "fastest .. method" above
- most of the work is tuningsw related, the firmware part is simple
Also some general method (see interpretere below) to define functions for misc output actuation
- WOT_OUTPUT_TPS_THRESHOLD should be specified in config_t or dropped (misc outputs there)
- wot_output needs hysteresis
- miscX_activity needs hysteresis
Interpreter
There are more and more stuff that needs flexible configuration, without firmware recompile, eg. misc outputs. Currently condition is wired for most common function, RPM,MAP,TPS ranges
I think we cannot avoid a simple language/interpreter. Maybe a postscipt-like (but binary) code: words of 16 bits that are
- either push variable "..." to stack
- or operation "..." that takes N variables from stack, operates on them and places result on stack
---
Michael's Ideas...
There are a few parts to this challenge. First of all it's necessary to cater to a potentially long list of functions. Adding canbus enabled switches allows for an impressive range of features. VSS encoders, clutch switches, ALS enable switches, boost knobs are all potential inputs. On the output side one can have as many outputs as there are spare channels. Potentially extra drivers could be available via CANbus.
First the outputs...
I assume at this point we're dealing with a finite number - limited by the number of spares you have. This could still number 8 or more.
Outputs may potentially be switched based on a number of parameters. Here are a few features I thought up:
fan control
- enable temp
- enable added steps to the IAC
- disable temp
- disable subtracted steps from the IAC
Vtec control
- enable rpm
- enable temp
- enable MAP
- Disable RPM
- Disable MAP
fuel pump (maybe pre-defined)
- prime time
Tach signal (maybe pre-defined)
- tach divider
PWM IAC
- frequency
- minimum duty
- maximum duty
intercooler fan and/or intercooler water spray
- enable IAT temp
- enable added steps to the IAC
- disable IAT temp
- disable subtracted steps from the IAC
Nitrous enable
- minimum RPM
- maximum RPM
- minimum TPS
- minimum MAP
- maximum MAP
shift light
- minimum rpm
- maximum rpm
misc output control
- minimum RPM
- maximum RPM
- minimum TPS
- maximum TPS
- minimum MAP
- maximum MAP
Table based PWM. - Jörgen
This is a function that allow more flexible Boost and launch control functionallity in addition to being useful for fuelpump and waterinjection control
- TPS, MAP, and any ADC count selectable for the Y-axis of each table. MAP and TPS is by far the most useful.
- Different bins for each table
- 6X6 tables
- Any output selectable
Another sort of output may need to be driven from a table. TGV/TVIS/AVCS/IAB control, electronic throttle and others come to mind.
For TGV/TVIS/AVCS/IAB and possibly iVTEC the computer may control offsetting one or more cams and/or adding to the lifts at different RPM and load combinations. Electronic throttle control will be the way of the future as more and more new cars are drive by wire. I suspect this will require a completely dedicated implementation. For the above the outputs are most likely to be PWM based. I can confirm that AVCS (on Subarus) is PWM controlled. I believe the same with the new i-VTEC found on hondas. Certain RPMs and MAP values require certain PWM outputs in order to aid in spooling the turbo or creating lower RPM torque.
Storage
The code for doing these checks is fairly trivial. Efficient storage of the parameters is somewhat less trivial.
A dynamic size for these functions would require a lot of work. First you would need a means of specifying the size of each record and secondly you would need a means of properly shuffling things around should changes be made. Anyone remember Norton Defrag?
The current implementation is rather short sighted and wasteful. You pay the overhead even if you don't use a feature. Unfortunately this implementation is more difficult because of the dynamic memory space. Using static sizing is as wasteful or worse than the existing solution.
There is lots of space in eeprom to store these but eeprom is a bad solution because it lacks any quick access method. As a result we are forced to read the values into RAM. Removing these from the 'C' table would free up about 30b of memory if the table size were reduced accordingly.
Personally I would prefer to have them stuck in flash. This would provide quick reads where the parameters would not necessarily need to be stored in RAM. Unfortunately this brings about a challenge for updates. While technically possible each parameter would be limited to about 10,000 changes. We're probably okay with this. The other challenge is halting the processor long enough to perform an update without missing an ignition event or some other time sensitive event. While tuning I'm not sure if you really want to write your flash page 100 times as you adjust values.
All in all I suspect we would need about 20*8 bytes of memory, be it flash or SRAM.
---
If a block contains 8 instructions (16 bytes), that can be do more than the current misc1 misc2 implementation, basically enough for any function that comes to mind. The fixed size block makes the defragmentation issue go away (the same way they allocate fixed size pages in OS-es).
Besides range checks and alike, there will be some complex functions as well.
We can add a
- "jump" instruction that makes it possible to use more than one 8-instruction blocks (even jump into the middle)
- "conditional jump" makes it very powerful
Shiftlight
We need to change shiftlight code a bit so the configured RPM treshold is compared againds RPM + dRPM/dt*0.5sec (not just RPM). This means the light (beeper, whatever connected) is activated somewhat earlier in gear1 and gear2 (but gearbox switches not needed).
Michael's Proposal
This will be merged to GenBoard/UnderDevelopment/FirmWare/DynamicConfigRelated, which is about saving space and versatility:
- only those features consume space that are actually used
- versatility means that things are possible that otherwise would not be possible - users often request different deviant (sometimes unreasonable) function
Michael suggest ripping following out of the config table and shortening that table.
structure for the outputs
offset | output type | slotid |
IGN0 | COIL | 255 |
IGN1 | COIL | 255 |
IGN2 | COOLINGFAN | |
IGN3 | COOLINGFAN | |
IGN4 | UNUSED | 255 |
IGN5 | UNUSED | 255 |
IGN6 | UNUSED | 255 |
IGN7 | UNUSED | 255 |
FET0 | FUELPUMP | |
FET1 | TACH | |
FET2 | WATERSPRAY | |
FET3 | VTEC | |
FET4 | INJECTOR | 255 |
FET5 | INJECTOR | 255 |
FET6 | INJECTOR | 255 |
FET7 | INJECTOR | 255 |
FET8 | WBO2 | |
FET9 | UNUSED | 255 |
FETA | UNUSED | 255 |
Assumng no pre-defined outputs like WBO2 heater, fuel pump, frees 40 bytes SRAM. Clearly does not worth to start with thist, ripping tables from SRAM is simpler and saves 1000 bytes.
Now for the slots... The features I could dream up with required anywhere from 1 to 8 bytes of space. In order not to be too wasteful I suggest definining different size slots and reserving a finite number of each.
Most people will want about 6 channels for injectors and coils. That leaves about 14 potential outputs.
number reserved | slot size | slotids |
6 | 4 | 0..5 |
2 | 8 | 6..7 |
The space here was arbitrarily chosen. It could be expanded as more memory is found through making code more efficient. These slots are expected to be permanently stored in EEPROM much the same as the config table is stored.
Finally a table would be created in flash with the following stucture.
slotsize | function pointer |
4 | &COOLINGFAN(output channel,slotid) |
8 | &VTEC(output channel,slotid) |
etc | etc |
Attaching a feature to an output channel would consist of looking at the slot size required then traversing the output list to find a slot of that size that is available. It would then be added to the list and the type assigned. The tuning interface or software would need to know about every different output type's settings and storage format so that data could be entered in the slut.
Then at given intervals the array would be traversed and each pointed to function called. The function itself would then be responsible for looking at the stored parameters in its slot and making a determination of what it should do.
Detaching a feature would be as simple as removing its entry from that output element in the outputs table.
For sanity the firmware should prevent assignment of outputs in the H table to slots that are not already reserved as type COIL or INJECTOR. Conversely when these values are changed from COIL or INJECTOR they will need to be removed from the H table.
Results
These limits could be adjusted with ease subject to memory availibility. The flexibility does not end here. Again, subject to memory availibility larger slots could be defined for items such as boost control or AVCS controllers/active diff lockup controllers.
The following config variables could then be removed.
uint8_t fan_temp;
uint8_t fan_hyst;
uint8_t fan_channel;
uint8_t engine_off_delay;
uint8_t pump_on_mintime;
uint8_t fuelpump_channel;
uint8_t misc1out_minrpm;
uint8_t misc1out_maxrpm;
uint8_t misc1out_mintps;
uint8_t misc1out_maxtps;
uint8_t misc1out_minmap;
uint8_t misc1out_maxmap;
uint8_t misc1out_channel;
uint8_t misc2out_minrpm;
uint8_t misc2out_maxrpm;
uint8_t misc2out_mintps;
uint8_t misc2out_maxtps;
uint8_t misc2out_minmap;
uint8_t misc2out_maxmap;
uint8_t misc2out_channel;
uint8_t act_wot_rpm;
uint8_t act_wot_channel;
uint8_t act_rpm_rpm;
uint8_t act_rpm_channel;
uint8_t boost_conf;
uint8_t boost_targetoffs;
uint8_t boost_minpressure;
uint8_t boost_pid_kp;
uint8_t boost_pid_ki;
uint8_t boost_pid_kd;
uint8_t boost_pid_ilimit;
uint8_t boost_channel;
uint8_t water_pump_temp;
uint8_t water_pump_hyst;
uint8_t water_pump_channel;
uint8_t tach_channel;
uint8_t tach_divider;
uint8_t shiftcut_conf;
uint8_t shiftcut_channel;
uint8_t shiftcut_time;
This would free 40 bytes of RAM (same amount of space reserved in EEPROM, but we have much space there). So this implementation could be completed without requiring any additional SRAM.
Storing in FLASH - handling "dirty" data and writing while engine is off
would save a lot of SRAM, but caching "dirty" config/tables and storing in flash has it's own problems (that we want to solve, within 3 months, because of ARM, but there are better things to do now to help the case).
Finally, it is technically possible to store all of the slots in flash. I don't like this solution because of the complexities of live updating the flash while the engine is running. This would suck when you're making rapid changes for tuning. Yes, changed slots could be buffered in RAM to an extent but then the system becomes very complex.
We surely need dynamic structures (similar to your proposal) in the future. However, MegaTune is not yet prepared for it. So for now, we must save SRAM with other ways. Notably, using tables directly from EEPROM, and scheduling EEPROM write to be directly after user-space calculations (and using a lockbit or examining storage.c state) to avoid interference.
EEPROM
I've just re-read the docs on reading/writing eeprom. It seems that
- 8.5ms stated for writing (1 cell, byte or 16bit?)
- and the 17ms (???) for reading
Firmware and MegaTune interface can be written for anything. In short, changes in stable will not be tolerated unless they have MegaTune support, or the MegaTune vemsv3.ini change is trivial.
A separate branch is OK though.