GenBoard/UnderDevelopment/FirmWare (2006-03-16 04:43:08)

This page lists for developers some items they can pick from

When changing the semantics of a variable or table, please write a note to GenBoard/UnderDevelopment/FirmwareChanges


GenBoard/UnderDevelopment/FirmWare/NextRelease specifies what tasks has to be done before we can create a new stable release.


The syntax of the page is inefficient. There should be a features relation with attributes:N

The TODO-list could be generated automatically, and the finalization of features should not require moving to another page (or table or whatever).


Priorities:

0: unknown (may be urgent too)

1. light-wish

2. wish

3. strong wish

4. planned far future

5. planned near future

6. planned very soon

7. urgent

8. urgent bugfix

9. critical bugfix


Strategical list

List of tasks that you can choose from if you want to join: Feel free to add new items, add your name if you feel like doing it (that does not mean others cannot participate), or start a discussion about them.


Misc. smaller TODO items


Some User request for the GenBoard 2.2-3.0

We should have a power-target sublayer that consolidates
  • ALS
  • launch-control and
  • traction control
  • idle-control
all are some way of controlling power, with a combination of
  • ignadv
  • boost
  • EGR
  • fuelcut
  • event-skipping, and
  • direct idle-air-valve control.
Is there a point to configure fixed beginning? From experts I hear that only the fixed ending makes sense (actually not much difference since the pulsewidth is also mainly determined by the loadsite).Fix beginning could be only an extra feature.But if we'll have only fix ending, that will be great too! fixed injection start angle is useless -Jörgen candidates: If the MAP bins are fixed you need (much) more bins, but with configurable MAP bins it is easy to start with 5..6 bins and add more if there is a serious break somewhere. VE or lambda tables should not have such breaks in the MAP direction in any case (max 1 break if injector opening is misconfigured). Only the ignadv has 2 breaks (for which 4 MAP bins are needed) the extra 4 bins can be used to smooth out all areas.

To prevent stepup to 16 .. 32 .. 64 .. 99 million bins we should examine the exact table and find the problem and determine benefits numerically.


LCD Related

Moved to GenBoard/UnderDevelopment/FirmWare/LcdRelated


INJECTOR_STAGING

GenBoard/UnderDevelopment/StagedInjectors


Michael's browsing through the firmware

TODO'S


How does bootloader handle inverted/noninverted igndriver?

The trick is in ioinit.c: the initialization block is inside

#if (defined __MEGASQUIRT_C__) || (! defined HARDWARE_PULLUP_OR_DOWN)

So in the bootloader, the pins are left as input if HARDWARE_PULLUP_OR_DOWN is defined (so the PWM-ing SIL5 10k does it's pullup job).


refcard needs serious updating


outputs

WOT_OUTPUT_TPS_THRESHOLD should be specified in config_t

wot_output needs hysteresis

miscX_activity needs hysteresis


menu.c:

menu.c:

edis.c:

for IGN_DUALOUT ch-1, ch==0 can cause problems, warn in the manual


fuelcalc.c:

config.warmup_rpm[] is a bit sick for 16x8 table. The idea was that at low RPM the config.warmup_clt[] multiplier could result in way too much fuel at high RPM. The RPM (r-array-table possibly 16 value!!!) selected config.warmup_rpm[] can downscale it (written <100 values). I propose a simple constant slope to downscale with increasing RPM. The other solution is to use additive quantity, not multiplier, but that breaks megatune compatibility.

I applied a small [corrwarmrail355.diff patch] to make corr.warm (which is afterstart + warmup enrichment) rail at *3.55 instead of old *2.55. The [has it applied]. Jorgen said his afterstart is higher than *2.55, Dave Brul's is railed at *2.55 and Marcell's engine seems to like more than *2.55 as well. It only matters for very small time as afterstart decays fast - but I think this railing at *2.55 prevented starting my engine in cold, when I refused to touch req_fuel or divider to hackstart it (after being confident in VE learned with warm engine earlier).

storage.c:

undovalue doesn't check if we are busy storing values to eeprom => can result in a long busy wait. Added return condition. See it again.

BUG'S

timing.c @ l526

secondary inj channels touches the last primary inj channel

DONE

fuelcalc.h @ l49

als reads port instead of pin

This is important: Look in the mega128 datasheet page 63; Reading the PORT register...bad! Instead PINn register must be read: fixed now.

ioinit.c @ l98

als should also init port value besides ddir

DONE

storage.c @ 78

m-tab in menu points to tables, not the structures, ex. m->tab = &ve.lambda not m->tab = &ve

Modified, see it again.


even more sophisticated IdleControl including CruiseControl and ALS


atomic RS232 logging

Done in wbo2.c (mates with wbo2log.pl)


verify calculated edgetime_corr coefficient

The visual gnuplot-linreg is OK, you can log WideBandO2 data to RS232 and verify with linreg.pl


pri=6

MUST-do sg. like this for GenBoard v3.0:

configurable with tables (vs. compiletime).

Each sequential output (like inj and ign) should be driven this way:


This stuff is DROPPED for now in favor of an even simpler, still powerful scheme

old port_act stuff for the curious:

that particular channel to

ignconf.c and injconf.c should be dropped (even more complex :-) :

bits 6:7 selects type of action: ign/injprimary/injsecondary/ ... /special,

bits 4:5 the off/gopwm/on (inj) or init/on/off (for ign)

bits 0:2 selects the channel 0..7 (bit 3 is future)

We can first write a generic handler that will use the lower 3 bits to determine the channel (tableline), later it can be unrolled for faster execution. Packing the bits in a better way could help gcc optimize well after unrolling. In each dispatcher() call up to 3 port_acts can be executed depending on the relevant port_acts read out from the table (00 bails out earlier, FF not!) as the 3 consequtive values in the relevant port-act config table.


(EEPROM) Storage related

As you know (storage.c) we have all tables and config (that live in EEPROM) mirrored in SRAM.

Config and h-table must stay in sram (or flash), so it is always available, even during EEPROM writing! (since it is used all over the place, including interrupts).

However, we'll have about 9 (!) 16*8 byte tables (it only took to change 2 constants - one VE_SIZE_RPM in firmware and $elements in make_tables.pl - to get 16 RPM bins, but it requires some more testing), which is not marginal.

Later we will need sg. like a debug flag, that enables writing these tables. So in mtt mode they will not be accidentally overwritten (misconfiguration of h table would change the behaviour fundamentally, but why is that a problem? ).

Suggested names tables:

large 16x8 tables (16 in the RPM, 8 in the kPa direction):

small 1x16 tables:

small 1x8 tables:

check the following for menu conflicts:


A good collection of subroutines, eg. I2C: http://hubbard.engr.scu.edu/embedded/avr/avrlib/

We should contribute at least pid, softpwm and eventqueue.

See also:

LoggerIntegration


The 16x8 tables are a good idea. I've never run into a situation where I felt that I needed more than 8 KPA values. From a marketing standpoint however more is better. It is unfortunately a sorry state if marketing must dictate features.

From a tuning standpoint it isn't all bad as sometimes more Kpa values would make for easier tuning rather than having to move existing points around whenever large changes in V/E are found. Case and point VE on variable valve timing motor depends on the switchover point.


TPSdot versus MAPdot. This is very setup dependant as the MAP will lag the TPS somewhat. I think both MAPdot and TPSdot should be implemented so the tuner can decide to use either or both.

I have implemented it, now it has been in the firmware (MembersPage/Gabor)


A config parameter is needed for the max KPA given the installed MAP sensor. Since the signal input is generally 0-5v regardless of the range of the sensor the ECU only needs to know the real KPA value for display purposes. Since the injection is based as a ratio subject to the injector opening time and size it could care less if you're at 1 bar or 4 bar. But it would be nice for the LCD to show the right values.


I have more or less stolen a tps calibration setup: Pretty obvoious, allow engine.tps pull tps_low lower and tps_high higher. Let tps_low and tps_high=sensors[TPS] whenever commanded so via menu or for some special occasion (ignition on for 20 sec without starting?) The otherwise stupid tps_low >= tps_high can also trigger this.


use the LSB bits of ADC

The ADC currently uses only the upper 8 bits of readings. This is mostly OK, but why not use all 10, or 12 (MCP3208) or more (using filtering). Actually, for WBO2 Ri calculations we use 10 bits samples of the nernst input.

I only know one point where it would be noticable: with (the common) speed-density setup the VE value is multiplied with MAP. For a 2.5bar MAP sensor the readings (using only 8 bits) for 30 and 31 kpa are appr. 30 and 31 (difference is 1 LSB) which is significant. With using 10 bits it becomes 120, 124 (4 LSBs), much nicer.

I'm thinking of killing the ifndef WBO2 ADC setup, and tweaking the WBO2 ADC to work with non-WBO2.

The sensor values must be accessed with getter functions get_sensor(x) (that can be inlined or macro-d), not like sensor[x]. (This will come very handy when the digital signal can come from other controllers later).

Do we need the prev_sensor_reading[] array ? We can just do\n

// exponential decay:
uint16_t t = get_sensor(x) + new_reading) >> 1;
cli(); // needed on AVR because 16 bits
set_sensor_value(x, t);
sei();

Note that the getter should work the same way no matter the signal comes from a local internal ADC, MCP3208 or a combination of 2 signals (like cold-junction compensation signal of a K-Thermo comes from a different channel), or from network. We might want different getter-wrappers for different bitwidths (an 8 and a 16 bit getter, the 8 is needed so the upgrade is simpler, and 8 bit is actually enough at most places).

should this be here?

MCP3208 was not tested extensively before this. MCP3208 is the only useful chip from microchip (the CAN transceiver was dropped from the short list because it does not support talking to an uC 3.3V :-), we'll use MCP3208 a lot. The SPI software went smooth, it worked on first try. Small issue that I first read channel6 (to display output of ADC597AD on the top) because Microchip named stupidly 1..8 instead of 0..7, but it was trivial to fix (and read channel 5). Do we want to rename signals on schematic? Or just remember...

Sampling freq:

We currently have 2 classes:

We should finally have:


can we kill the handler2k?

any low priority maintenance task


do the timing from last possible tooth - AdvancedIgnition


pri=2

I think megatunix is safe, anyone confirm this? yes.

We couldn't reproduce the problem with the same genboard with another computer (and megatune). It seems the USB-RS232 converter caused the problem by making rare errors in the AVR => PC direction (bootloader was fine, although the bootloader moves very little info from AVR => PC : checksum only)


menu entries for testing Hardware - DONE

mdn03mdn02mdn01mdn00 will fire 3, 2, 1, 0 ignition outputs (actual outputs determined by the h[2] table), all ignchannels on a 4 cyl direct ignition or 8 cyl wasted spark.
  • The igbt fires after the number is entered
  • Note that the pulses are short, determined by engine.dwell

Any advanced testing helper should go to the PC side (eg. one that steps through the outputs and activates one at a time).


Heap scaledown - DONE (TODO: merge this chapter to OnlineCourse/EventQueue)

The dual-heap EventQueue supported scheduling to 262 msec far into the future.

We decided to spare some SRAM, flash, complexity and processing time by killing the dual-heap implementation (for a simpler one).

The dual heap implementation was used so comparison between 2 events is possible, without the overflow screwing up result. Note that comparison with "etime.now" is not an issue:

uint16_t diff = key - now;

if(diff >>8) == 0xFF than the event must be executed ASAP.

With a little trick (key is 1020 usec or 255 higher than real execution time) if(diff >>8) == 0 condition can be used (even faster).

The problem with one heap is comparing 2 event-keys, the max difference between 2 event-keys must NOT be greater than 32767 (or 131 msec), otherwise the comparison would return bad result in some cases. 131 msec means that timing from an even-type trigger to 100 degrees (pretty extreme setup) would only work down to 127 RPM (not below). Fortunately this is fine (if not, it could be solved nicely of course).


Trigger scaledown

trigger should consist of only the following actions:

This depends on userspace preparing an execution plan, sg. like:

ignition should be fired n degrees after p-th tooth: in interrupt this means very simple condition (maybe it could also check if trigger frequency did not change drastically, or something...) and very simple calculation.


Priority-based mainloop scheduler prio=4

I propose a simple userspace (mainloop) scheduler with 4 prio levels (queues):

Notes:

It is also possible to have an eventqueue that is executed in userspace (instead of softelapsed), not interfering with interrupt execution (the heaproot would only be considered for execution when the mainloop thinks so). Caveats:


Flexible analog output ( OC3C )

An analog output (maybe external GND referenced) should be easy to configure. Could be configured as MAP,WBO2, NBO2, ignadv, injpw, RPM etc...

This would allow

The WBO2 output is high priority at least

Someone please make sure the most used curves are linked near from GenBoard/Manual/WBSensor'''


PRG_RDB and PRG_RDW fix

If firmware ain't compile with latest avr-libc, we must consider to change all PRG_RDW and PRG_RDB to pgm_read_word() and pgm_read_byte()

as on the patch on MembersPage/AlexanderGuy page.

Probably somewhat better tö make wrappers. We need wrapping eg. for PC anyway. Remember firmware is not avr-libc only. Going towards ARM and even running on OnlineCourse/PcEmulation. So wrapping is good.

Eg. in global.h\n

somthing like ...
#ifndef PRG_RDW 
#define PRG_RDW(x)  pgm_read_word(x)
#endif

Hey, but there is already something in there :
#define PRG_RDW(a) ((PRG_RDB((unsigned char*)(a)) & 0x00FF) | ((PRG_RDB((unsigned char*)(a)+1))<<8))

strangely, also:
#define pgm_read_word(a) ((PRG_RDB((unsigned char*)(a))
 & 0x00FF) | ((PRG_RDB((unsigned char*)(a)+1))<<8))

#define pgm_read_word_near(a) ((PRG_RDB((unsigned char*
)(a)) & 0x00FF) | ((PRG_RDB((unsigned char*)(a)+1))<<8))
#define pgm_read_byte(a) (PRG_RDB((unsigned char*)(a)))

The fix must be flexible and work for older avr-tools as well. (eg. many people use latest winavr).