Point of this change is to allow using these functions for
writing to the display, too, without duplicating all the code.
To reduce confusion, functions were renamed (they're no longer
'serial', after all:
serwrite_xxx() -> write_xxx()
sersendf_P() -> sendf_P()
To avoid changing all the existing code, a couple of macros
with the old names are provided. They might even be handy as
convenience macros.
Nicely, this addition costs no additional RAM. Not surprising, it
costs quite some binary size, 278 bytes. Sizes now:
Program: 24058 bytes 168% 79% 38% 19%
Data: 1525 bytes 149% 75% 38% 19%
EEPROM: 32 bytes 4% 2% 2% 1%
Regarding USB Serial: code was adjusted without testing on
hardware.
You see where the journey is going? This is the equivalent to the
function to write a character to the serial line, so we can
basically swap these two in other functions.
Monospaced fonts require a bit less space, right now it saves a
nice 110 bytes binary size.
Actually, the distinction between monospaced and proportional
fonts was in font.h already, so not supporting them was a bug.
But so far we have no monospaced font, so nobody noticed.
Note by Traumflug: this code was written by Ruslan Popov a lot
earlier already. I picked it to i2c_test.c to get "something"
visible running. This is the commit finally adjusted to the new
display infrastructure.
While this could also be done properly now, with a couple of
additional fonts, this would require quite some time. However,
it's more important to have at least one display working now,
rather than having a ton of sophisticated eye-candy, which isn't
even user-visible, because the upper layers are still missing.
What 'make size' previously reported was misleading, because
it didn't count the .data section as Flash usage. However, this
section is actually written to Flash.
The .data section holds the data needed for inititalising
variables. As such it counts to both, Flash and RAM usage.
Nice verification: reported 'Program' size now matches upload
size reported by avrdude exactly.
There's now the tool 'avr-size', which makes reading such stuff
much easier:
avr-size -C build/teacup.elf
Example output:
AVR Memory Usage
----------------
Device: Unknown
Program: 23704 bytes
(.text + .data + .bootloader)
Data: 1543 bytes
(.data + .bss + .noinit)
EEPROM: 32 bytes
(.eeprom)
So far for choices based on boolean sets, only, because choices
for values typically need no more readable names.
This elegantly removes the somewhat ugly check for '(', too.
Having a choice with a defined set of options is nice, but it
also requires these options to be #defined somewhere _before_
entering config.h. To keep class-like encapsulation, we'd need
two header files for each code unit, one for the options, another
one for the usual header.
That said, we use other examples of such options, e.g. CPU, F_CPU
or KINEMATICS. For CPU and F_CPU it works fine, because their
options are numbers or other values known by the compiler. For
KINEMATICS it kind of works, because this #define is used in only
one place ... and there it's suboptimal already, because no option-
set.
Anyways, I was unsure about this change and if it turns out to be
a poor decision later, it can be reverted.
Most work by Ruslan Popov, collected from various commits and
made compatible with regression tests by Traumflug.
Display test code is now enabled by #defining DISPLAY_BUS to
i2c_twi.
As we usually talk to one device only, there's not much point in
carrying around the address all the time. Surprise, this saves
only 16 bytes binary size despite of heavy usage.
So far calling code had to wait long enough between individual
transmissions to make sure they end up in distinc ones. Now
calling code can stuff as fast as it wants, i2c_write() takes
care of the distinction.
This removes the need to write in full blocks, so data can be
sent from loops and/or program memory.
This capability allows to clear the screen without too much
effort, see i2c_test.c.
Still two weaknesses left:
- Transmission end is currently detected by ringbuffer becoming
empty, so delays are needed to make sure a transmission is
completed before the next one is sent to the buffer.
- Error handling is still only half existent. Any error on the
bus will stop I2C entirely. A recovery strategy is required.
Sizes show, taking into account the additional screen clearing
code, no significant change:
FLASH : 23216 bytes
RAM : 2052 bytes
EEPROM : 32 bytes
Naively restarting I2C immediately is certainly not the solution
and just leads to an interrupt flood. As I2C is currently meant
to drive displays, where successful data transmission isn't
crucial, we now simply stop transmission on errors.
This saves another 80 bytes binary size:
FLASH : 23094 bytes
RAM : 2051 bytes
EEPROM : 32 bytes
This commit squashes in some fixes found after debugging on the
topic branch. Test code by Traumflug, collected from Ruslan's
code on the topic branch.
Before, same as now without I2C:
FLASH : 22408 bytes
RAM : 1393 bytes
EEPROM : 32 bytes
Now with I2C:
FLASH : 23224 bytes
RAM : 2057 bytes
EEPROM : 32 bytes
This totals to some 800 bytes with a whole lot of test code, so
implementation is pretty small :-)
The existing code eschews "break" apparently thinking that it will
exit the loop prematurely. In fact this will only exit the switch
correctly. The loop will run as normal.
Maybe it's not a big deal, though, since the sensors get re-inited
each time the type of sensor is encountered in the loop. Presumably
it's ok for each of these sensors to get inited multiple times. If
that's always the case, maybe there's no problem here. But with the
current code sensor types might be initialized even when there is no
sensor defined for that type if the TEMP_* boolean is #defined.
For example, if I have this in my config:
#define TEMP_MAX6675
#define TEMP_MCP3008
//#define TEMP_INTERCOM
DEFINE_TEMP_SENSOR(extruder, TT_MAX6675, AIO5, 0)
DEFINE_TEMP_SENSOR(bed, TT_MAX6675, AIO7, 0)
Then the MAX6675 initialization code will be run twice and the MCP3008
code will, too, even though no temp sensor is defined for that type.
This change does not address the "init runs twice" problem. It only
addresses the "initialization of unused types" problem.
Use a binary search to find our target temperate in fewer
comparisons. The search algorithm is ostensibly slower because
it involves a division, but it's a div-by-two so should be
optimized into a simple bit-shift. Fewer comparisons involves
fewer pgm_read_words and should be faster overall, but the gain
is arguably tiny.
Note by Traumflug:
According to @Wurstnase's performance measurements, gain is
actually pretty huge. Temp conversions 0..1024 before this
and the previous few commits:
minimum: 1011.84 clock cycles.
maximum: 1993.92 clock cycles.
average: 1768.85 clock cycles.
Now:
minimum: 437.72 clock cycles.
maximum: 494.76 clock cycles.
average: 470.278 clock cycles.
That's a speedup by factor 3.7 on average!
Save a division at runtime by pre-calculating the slope between each
pair of adjacent thermistortable values. Since we use the larger value
each time, save the slope between two values A and B in the table
with the B data. Therefore the slope is that between each value and
its predecessor in the list.
Store this new value in the third element of the now 3-integers-wide
array which makes up the table. Use fixed-point 6.10 format to store
the slope. This is almost too narrow for some slopes and maybe it
should be changed to 8.8 fixed-point. In practice this presents a
loss in accuracy, but it is still significantly better than the
previous fixed-sample-size table production method. In particular no
provision is made to handle values which scale over 65535, and it
seems we should at least warn about this if not simply fail before
letting the user go off compiling his code.
Add a new flag TEMPTABLE_FORMAT and define it as 1 to tell the code
that we are using this new and incompatible format. This lets us
tolerate old hand-crafted thermistor tables by keeping the slower
algorithm in case one is still used. New thermistor tables should be
defined with this new format and with the FORMAT define set accordingly.
With the default 25 samples this adds 100 bytes to the flash image for
the thermistortable storage for two different thermistors. But the
code is simplified and saves me 134 bytes in the bargain for a net
decrease in flash size of 34 bytes.
The Thermistortablefile.py routine prematurely drops the
fractional part of the temperature when computing the 14.2
temperature values to emit in the code. Keep this instead until
the last moment when we finally calculate the integer format we
will store.
Teach simulator to calculate temperatures for all possible ADC
values using the compiled-in temperature tables and report the
resulting conversion. Do no other run-time simulation; exit
after reporting the conversion results. Output is suitable for
gnuplot for example like this:
gnuplot --persist -e "plot '< ./sim -T0' u 1:2 with lines,
'< ./sim -T1' u 1:2 with lines"
Decided to not include project files into the repo, because the
projects seem to include some absolute paths, which is not good
for developer cooperation.