The last log (Bit shuffling: what goes where ?) explains how the address bits are shuffled. Once the logical value and all the modes/options are obtained, these informations are compiled to generate a 32-bits word that is output to the file, which will program the Flash.
There are two conversion functions : hexadecimal and decimal. They are very similar and in fact can be merged into one, since the base parameter can work very well with this system (I just realise that in ASCII systems, it's better to have separate conversion routines, but here it's pointless). So let's just forget about function pointers...
Given the base parameter, it's easy to decompose the number into digits. There is only one corner case to deal with : what to display when the input is zero. Of course it should display ___0 (and not a void screen, or else people wonder if the circuit works at all) but there are 2 ways to achieve this :
- initialise the display to ___0 and use a while(>0){} loop (which is not entered in the only case where it is zeo)
- or initialise to nothing (____) and use a do..while (repeat...until) so the remainder of zero is written at least once.
The 2nd choice is better because the init value is all-cleared and the corner case happens only once, the do-while loop is lighter.
So we have the following code:
DigitLUT=[ "0", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "A", "B", "C", "D", "E", "F"];
// The previously described recursive function
function recurse( index, logic, sign, zero_ext, base) {
msg+=" "+logic;
if (index>0){ //0) {
var bit=BinLUT[index--];
recurse(index, logic, sign, zero_ext, base);
if (bit < 0) {
// special code for the modes
switch(bit) {
case -1: sign=1; break;
case -2: zero_ext=42; break;
case -3: base=16; break;
}
}
else
logic|= 1 << bit;
recurse(index, logic, sign, zero_ext, base);
}
else {
// This is a "leaf" call,
// where conversion takes place:
var i=0; // index of the digit;
var d; // the digit
var m="\n";
do {
d=(logic % base)|0;
logic= (logic/base)|0;
m=DigitLUT[d]+m;
} while (logic > 0);
msg+=" - "+m;
}
}
This code seems to work pretty well (once you solve rounding/FP issues with JavaScript by ORing 0)
------ -1
0 0 0 - 0
16384 - 16384
32768 32768 - 32768
49152 - 49152
------ -3
0 0 0 0 0 - 0
16384 - 4000
32768 32768 - 8000
49152 - C000
This code is directly inspired by traditional conversion functions from binary to ASCII. However our case differs substantially from an ASCII terminal because each new iteration writes to a different digit, corresponding to different codes.
In JavaScript or other similar languages, this is where multi-dimensional arrays become useful: there are 5 arrays (one for each digit) with 16 sub-arrays (for all the values). The counter i starts to be useful...
Well, being a rebel, I prefer to use a single array with 5×16 entries and increment i by 16.
var i=0; // index of the digit;
var d; // the digit
var m="\n";
do {
d=(logic % base)|0;
logic= (logic/base)|0;
m=DigitLUT[d+i]+m;
i+=16;
} while (logic > 0);
Then, it's "only a matter" of generating the rght bit pattern for each number.
Yes, the time has come to work on this...
The data pins are connected to the respective segments:
D 1 2 0 F2 1 F1 2 F3 A3 3 G3 C3 4 C1 G1 5 B1 F0 6 D1 E1 7 C0 D0 8 A2 B2 9 A1 F1 10 E3 D3 11 F2 B3 12 E2 G2 13 G0 E0 14 D2 C2 15 B0 A0Conversely, and more interesting, the segments are connected to the following data pins (+16 means connected to phase F2)
DigitPins=[
// A B C D E F G
[ 15+16, 15 , 7 , 7+16, 13+16, 5+16, 13 ],
[ 9 , 5 , 4 , 6 , 6+16, 9+16, 4+16 ],
[ 8 , 8+16, 14+16, 14 , 12 , 11 , 12+16 ],
[ 2+16, 11+16, 3+16, 10+16, 10 , 2 , 3],
];
Let's combine these pin numbers with the list of active segments (0=A, 1=B, etc.)
Numbers=[
[ 0, 1, 2, 3, 4, 5 ], // 0
[ 1, 2 ], // 1
[ 0, 1, 3, 4, 6 ], // 2
[ 0, 1, 2, 3, 6 ], // 3
[ 1, 2, 5, 6 ], // 4
[ 0, 2, 3, 5, 6 ], // 5
[ 0, 2, 3, 4, 5, 6 ], // 6
[ 0, 1, 2 ], // 7
[ 0, 1, 2, 3, 4, 5, 6 ], // 8
[ 0, 1, 2, 3, 5, 6 ], // 9
[ 0, 1, 2, 4, 5, 6 ], // A
[ 2, 3, 4, 5, 6 ], // B
[ 0, 3, 4, 5 ], // C
[ 1, 2, 3, 4, 6 ], // D
[ 0, 3, 4, 5, 6 ], // E
[ 0, 4, 5, 6 ] // F
];
(ok this looks a lot like what I have done already for the #Discrete YASEP at "Redneck" disintegrated 7 segments decoder)
The first four digits can be compiled with these two arrays. The fifth digit is explained in the very first log: Decoding the extra digit
Value: 0 1 Y 2 W + Z 3 Y + Z 4 X + Y 5 X + Z 6 W + X + Z Intermediate coding: W = F1, ph=1 (phase 2) X = F2, ph=1 (phase 2) Y = F1, ph=0 (phase 1) Z = F2, ph=0 (phase 1)
Knowing (from above) the values of F1, F2 and the phases, it's easy to make the values by hand.
Y = 1 << /*F1 =*/ 1;
Z = 1 << /*F2 =*/ 0;
W = 1 << /*F1+16 =*/ 17;
X = 1 << /*F2+16 =*/ 16;
SegmentLUT={
33: Y , // 1
34: W + Z, // 2
35: Y + Z, // 3
36: X + Y , // 4
37: X + Z, // 5
38: W + X + Z // 6
};
Now, a simple nested triple-loop combines the segments and the digits.
var k=0;
for (var j=0; j<4; j++) { // iterate the digits
for (var i=0; i<16; i++) { // iterate the values
var n=0;
// iterate the segments
for (var l=0; l< Numbers[i].length; l++)
n |= 1 << DigitPins[j][Numbers[i][l]];
// save the accumulated value
SegmentLUT[k++]=n;
}
}
You can check the result with the following code: function toBin(n) {
var m="", c;
for (var i=0; i<32; i++) {
c=" ";
if (n & 1)
c="#";
m=c+m;
n=n>>>1;
}
return m;
}
for (var i=0; i<=70; i++)
msg+=i+" "+toBin(SegmentLUT[i])+"\n";
This shoudl give you something like that:
From there, things become pretty easy :-)
For example, we have the values of all the numbers at every position so we can create the initial value of 0000
var AllZero=
SegmentLUT[0]
|SegmentLUT[16]
|SegmentLUT[32]
|SegmentLUT[48];
Note that most segments (30 out of 35) are turned on so the power consumption is close to maximal. Maybe zero-extension is not such a good idea after all but we'll see in practice... Now we can return to the leaf call of the recursive function. Here is what must be done:
- unconditionally remove the precedent digit ("clear" with a ~8) from the zero_ext
- lookup the new pattern from SegmentLUT and add it to zero_ext
- output the result
var n=zero_ext;
do {
d=(logic % base)|0;
logic= (logic/base)|0;
n = (n & ~SegmentLUT[i+8])
| SegmentLUT[i+d];
i+=16;
} while (logic > 0);
output(n);
I have suffered a few lame inattention bugs (thanks to JS' weak checking) but the whole program works like a charm and must now be ported to C.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.