UNTESTED: still playing with eeprom-macro

originally, it seemed that the little endian version of write...(), and
the big endian version of read...() would be the easiest.  this was
true, when i first wrote the functions.  after optimization, the big
endian write...() got much better, but for some reason, i couldn't quite
crack the little endian read...().  perhaps i'm missing something.  in
any case, the big endian versions of both look quite good to me now, so
they're what i'll be going with.  too bad the little endian versions
didn't quite work out... but i was expecting to go with the big endian
versions anyway, since we'll be reading much more often than writing.

// - sizes for each function (in bytes) (with optimizations on):
//
//                            function  frame  stack
//       read  big endian         154      3     10
//       read  little endian      200      2     10
//       write big endian         160      0      6
//       write little endian      172      0      5

also, note that while optimizing, i was looking only at compiled
function size, and frame and stack usage: actual profiling would have
been a bit difficult, and i don't feel like writing versions of the
algorithms for testing on my laptop right now (though, i might later,
for fun, if i can give it as an assignment to the class i hopefully TA
for next semester - hehe).  i tried to pay attention to the amount of
code inside the loops though, when i was changing things, and i'm under
the impression that the AVR has fairly predictably timed assembly
instructions (1 or 2 cycles each?), so compiled function size seemed
like a good proxy.

done experimenting with this for now.  yay! :) .  i'll remove the extra
code in the next commit.
partial-rewrite
Ben Blazak 2013-12-23 22:26:43 -08:00
parent 55e96d5413
commit f0fcfca4ef
1 changed files with 43 additions and 26 deletions

View File

@ -21,11 +21,10 @@
* with the least significant byte occupying the lowest address. Protocols,
* data formats (including UTF-8), and such are primarily big endian. I like
* little endianness better -- it feels more mathematically consistent to me
* -- but after writing a bit of code, it seems that while writing is easier
* to do as little endian, reading is easier to do as big endian; and since
* we'll be reading much more often than writing, big endian seems like the
* logical choice. For that reason, this code organizes bytes in a big
* endian manner whenever it has a choice between the two.
* -- but after writing a bit of code, it seems that big endian
* serializations are easier to work with, at least in C. For that reason,
* this code organizes bytes in a big endian manner whenever it has a choice
* between the two.
*
* - For a long time, I was going to try to make this library robust in the
* event of power loss, but in the end I decided not to. This feature is
@ -152,8 +151,8 @@ typedef struct {
//
// function frame stack
// read big 154 3 10
// read little 200 3 12
// write big 208 0 9
// read little 200 2 10
// write big 160 0 6
// write little 172 0 5
/**
@ -187,17 +186,30 @@ key_action_t read_key_action_little_endian(void * from) {
uint8_t byte = eeprom__read(from++);
key_action_t k = {
.pressed = byte >> 6 & 0b01,
.layer = byte >> 4 & 0b11,
.row = byte >> 2 & 0b11,
.column = byte >> 0 & 0b11,
.pressed = ( byte & 0x40 ),
.layer = ( byte & 0x30 ) << 2,
.row = ( byte & 0x0C ) << 4,
.column = ( byte & 0x03 ) << 6,
};
for (uint8_t i=2; i<8 && byte>>7; i+=2) {
uint8_t i = 0;
for (; byte>>7; i++) {
byte = eeprom__read(from++);
k.layer |= ( byte >> 4 & 0b11 ) << i;
k.row |= ( byte >> 2 & 0b11 ) << i;
k.column |= ( byte >> 0 & 0b11 ) << i;
k.layer >>= 2;
k.row >>= 2;
k.column >>= 2;
k.layer |= ( byte & 0x30 ) << 2;
k.row |= ( byte & 0x0C ) << 4;
k.column |= ( byte & 0x03 ) << 6;
}
for (; i<4; i++) {
k.layer >>= 2;
k.row >>= 2;
k.column >>= 2;
}
return k; // success
@ -210,21 +222,26 @@ uint8_t write_key_action_big_endian(void * to, key_action_t k) {
if (to > EEMEM_END-3)
return 1; // error: might not be enough space
int8_t i = 0;
uint8_t byte;
uint8_t i = 0;
byte = k.layer | k.row | k.column;
while (byte >>= 2)
i += 2;
for (; i<3 && !((k.layer|k.row|k.column) & 0xC0); i++) {
k.layer <<= 2;
k.row <<= 2;
k.column <<= 2;
}
byte = (k.pressed ? 1 : 0) << 6;
for (; i>=0; i-=2) {
byte = byte | ( i>0 ? 1 : 0 ) << 7
| ( k.layer >> i & 0b11 ) << 4
| ( k.row >> i & 0b11 ) << 2
| ( k.column >> i & 0b11 ) << 0 ;
uint8_t byte = (k.pressed ? 1 : 0) << 6;
for (; i<4; i++) {
byte = byte | ( i<3 ? 1 : 0 ) << 7
| ( k.layer & 0xC0 ) >> 2
| ( k.row & 0xC0 ) >> 4
| ( k.column & 0xC0 ) >> 6 ;
eeprom__write(to++, byte);
byte = 0;
k.layer <<= 2;
k.row <<= 2;
k.column <<= 2;
}
return 0; // success