-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprocessing.c
1748 lines (1647 loc) · 49.4 KB
/
processing.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*****************************************************************************/
/* processing.c : the processing part of Soarer's Converter */
/*****************************************************************************/
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/boot.h>
#include <util/atomic.h>
#include <util/delay.h>
#include <string.h>
#include "hwdefs.h"
#include "soarer.h"
#include "intkeys.h"
#include "salloc.h"
#include "usb_comm.h"
#include "print.h"
#include "processing.h"
/*****************************************************************************/
/* Global data */
/*****************************************************************************/
uint8_t cur_select_set = 1; // 0x011e current select set
uint8_t req_select_set = 1; // 0x011f requested select set
uint8_t *layerdata = 0; // 0x016d/e big layer array
uint8_t allocated_layers = 0; // 0x016f # mem-allocated layers
uint8_t layer_cnt = 0; // 0x0170
uint8_t **layer_map = 0; // 0x0171/2 layer map (pointers into EEPROM)?
uint8_t max_used_layer = 0; // 0x0173 # layers in EEPROM?
uint8_t fn_curset = 0; // 0x0174 bitmask of currently pressed FN1..8 keys
uint8_t *fn_keyset = 0; // 0x0175/6 bitmask of FN modifiers for each pressed key
uint8_t modif_curset = 0; // 0x0177 bitmask of currently pressed modifier keys
uint8_t *macro_data = 0; // 0x0178/9 5-byte tuples
// 0 .....
// 1 .....
// 2 .....
// 3/4 ... EEPROM address of additional data
// 1st 2 bytes there are counts (0..63)
// of 2-byte tuples
uint8_t allocated_macros = 0; // 0x017a # allocated tuples in 0x0178/9
uint8_t macro_cnt = 0; // 0x017b # filled tuples in 0x0178/9
uint8_t setup_done = 0; // 0x017c flag whether setup completed
volatile uint8_t writing_eeprom_buffer = 0; // 0x017d
uint8_t layerdefs = 0; // 0x017e
uint8_t max_layer = 0; // 0x017f
uint8_t total_macros = 0; // 0x0180
uint8_t macro_onbreaks = 0; // 0x0181 # onbreak macros (still tentative)
uint8_t proc_keyboard_codeset = 0; // 0x0182
uint16_t proc_keyboard_id = 0; // 0x0183
uint8_t key_queue_widx = 0; // 0x0195
uint8_t key_queue_ridx = 0; // 0x0196
uint8_t hidx_trans[256] = {0}; // 0x019a looks like current remap layer
uint8_t *modif_keyset = 0; // 0x029a/b bitmask of modifiers for each translated key
volatile uint16_t eeprom_write_eeaddr = 0; // 0x029c
volatile uint8_t eeprom_write_cnt = 0; // 0x029e
volatile uint8_t eeprom_write_flag = 0; // 0x029f
volatile uint8_t *eeprom_write_buffer = 0; // 0x02a0
uint8_t pressed_hidxs[32] = {0}; // 0x02e3..0x0302 bitmask of currently pressed HIDXs
uint16_t key_queue[80] = {0}; // 0x030b .. 0x03aa
/*****************************************************************************/
/* get_layernum : retrieve the layer # for a key */
/*****************************************************************************/
// A_236c
// double checked
uint8_t get_layernum(uint8_t hidx)
{
uint8_t i; // R25
uint8_t *p;
// works its way through an array of 2-byte items; if
// incoming parameter matches byte #0, byte #1 is returned
for (i = 0, p = layerdata; i < layer_cnt; i++, p += 2)
if (p[0] == hidx)
return p[1];
return 0;
}
/*****************************************************************************/
/* translate_hidx */
/*****************************************************************************/
// A_2398
// double checked
uint8_t translate_hidx(uint8_t keyid, uint8_t make)
{
uint8_t t_hidx;
if (max_used_layer) // if layers used
{
uint8_t layer;
// A_23ac
if (make)
fn_keyset[keyid] = fn_curset; // remember current FN set with unmodified key
// A_23c2
// R2829 = keyid;
// A_23c6
layer = get_layernum(fn_keyset[keyid]);
if (layer && (layer <= max_used_layer))
{
// A_23e4
uint8_t lt_hidx = layer_map[layer - 1][keyid];
if (lt_hidx)
t_hidx = lt_hidx;
else
// A_2410
t_hidx = hidx_trans[keyid];
}
else
// A_2418
t_hidx = hidx_trans[keyid];
}
else
// A_2418
t_hidx = hidx_trans[keyid];
// A_2422
if (IS_FN_KEY(t_hidx)) // if FN1..FN8
{
// A_2432
if (make)
// A_243e
fn_curset |= 1 << (t_hidx & 0x07);
else
// A_2450
fn_curset &= ~(1 << (t_hidx & 0x07));
// A_2466
return 0;
}
// A_2468
return t_hidx;
}
/*****************************************************************************/
/* reset_layers : resets layer data */
/*****************************************************************************/
// A_2474
// Double checked
void reset_layers(void)
{
allocated_layers = 0;
layer_cnt = 0;
max_used_layer = 0;
layerdata = 0;
layer_map = 0;
fn_keyset = 0;
}
/*****************************************************************************/
/* reset_layer_trans : clears memory and resets buffer */
/*****************************************************************************/
// A_249a
// Double checked
void reset_layer_trans(void)
{
uint8_t i;
reset_layers(); /* reset all data and pointers */
i = 0; /* reset remap to 0..ff */
do
{
i--;
hidx_trans[i] = i;
} while (i);
}
/*****************************************************************************/
/* setup_layer : */
/*****************************************************************************/
// A_24b0
// double checked
void setup_layer(uint8_t keyid, uint8_t layer)
{
if (layer_cnt < allocated_layers)
{
uint8_t *p = layerdata + (layer_cnt * 2);
// A_24be
p[0] = keyid;
p[1] = layer;
layer_cnt++;
}
// A_24dc
}
/*****************************************************************************/
/* reset_fnset : */
/*****************************************************************************/
// A_24de
// Double checked
void reset_fnset(void)
{
fn_curset = 0;
if (fn_keyset)
memset(fn_keyset, 0, 256);
}
/*****************************************************************************/
/* read_remap : sets up a layer's remap table from EEPROM */
/*****************************************************************************/
// A_2506
// Double checked
void read_remap(uint16_t eeadr, uint8_t cnt, uint8_t layer)
{
if (layer <= max_used_layer)
{
uint8_t i;
uint8_t *bufptr = (layer) ? layer_map[layer - 1] : hidx_trans;
for (i = 0; i < cnt; i++, eeadr += 2)
bufptr[eeprom_read_byte((const uint8_t *)eeadr)] =
eeprom_read_byte((const uint8_t *)(eeadr + 1));
}
}
/*****************************************************************************/
/* alloc_layers */
/*****************************************************************************/
// A_259e
// Not 100% sure yet, but fairly confident
// (anything starting at A_2600 looks QUITE different to original)
uint8_t alloc_layers(uint8_t layers, uint8_t max_used)
{
uint8_t i;
uint8_t *layerptr;
if (!max_used)
return 1;
// A_25b4
fn_keyset = (uint8_t*)memalloc(256); // some malloc
reset_fnset(); // reset array allocated above
// A_25c4
// allocate one big array
layerdata = (uint8_t*)memalloc(2 * layers +
(256 + sizeof(uint8_t*)) * max_used);
if (!layerdata)
return 0;
// A_25f8
allocated_layers = layers;
max_used_layer = max_used;
// A_2600
layer_map = (uint8_t**)(layerdata + (layers * 2));
// A_2612
layerptr = (uint8_t *)layer_map + 2 * max_used; // pointer after end?
for (i = 0; i < max_used; i++)
{
// A_2624
layer_map[i] = layerptr;
// A_2634
memset(layerptr, 0, 256);
layerptr += 256;
}
/* The following layout is created:
layerdata:
| (2*layers) | (2*max_used) | (256 * max_used) | | (256 * max_used) |
| uninitialized | pointers | area 1 | ... | area (max_used - 1)|
| ............. | pp pp pp pp | 0000000000000000 | | 000000000000000000 |
^ | ^ ^
| +-------------+------------------...----+
layer_map -------+
The start of layerdata is filled with a set of (FN key HIDX, layer#) tuples in
setup_layer(). */
return 1;
}
/*****************************************************************************/
/* set_setup_done */
/*****************************************************************************/
// A_2662
void set_setup_done(void)
{
setup_done = 1;
}
/*****************************************************************************/
/* reset_setup_done */
/*****************************************************************************/
// A_266a
void reset_setup_done(void)
{
setup_done = 0;
}
/*****************************************************************************/
/* find_macro : looks up a macro for a key and returns its address */
/*****************************************************************************/
// A_2670
// double checked
uint16_t find_macro(uint8_t hidx, uint8_t modif_set)
{
uint8_t *pmacro;
uint8_t i;
for (i = 0, pmacro = macro_data; i < macro_cnt; i++, pmacro += 5)
{
// A_2682
if (*pmacro == hidx)
{
// A_2688
// Byte 1 are the modifiers that have to be set
// Byte 2 is -"- plus modifiers that have to be clear
// upper nibble is treated differently
// ... or so. Not completely clear yet.
uint8_t b1 = pmacro[1];
uint8_t b2 = pmacro[2];
// get modifiers that should be set and are set
uint8_t cmset = b1 & ~b2 & modif_set;
cmset >>= 4; // overlay right and left modifier keys
modif_set |= cmset; // Not sure whether this is good ... but definitely so
if (!((b1 ^ modif_set) & b2))
return *(uint16_t*)(pmacro + 3);
}
}
// A_26ae
return 0;
}
/*****************************************************************************/
/* reset_macro_data */
/*****************************************************************************/
// A_26b6
// double checked
void reset_macro_data(void)
{
setup_done = 0;
allocated_macros = 0;
macro_cnt = 0;
#if 0 // totally useless, only WASTES time
if (macro_data)
#endif
macro_data = 0;
}
/*****************************************************************************/
/* jmp_reset_macro_data : just a little dispatcher (wtf?) */
/*****************************************************************************/
// A_26d8
// double checked
void jmp_reset_macro_data(void)
{
// presumably, something's been commented out in the original code.
reset_macro_data();
}
/*****************************************************************************/
/* reset_modifset */
/*****************************************************************************/
// A_26dc
// double checked
void reset_modifset(void)
{
modif_curset = 0;
if (modif_keyset)
memset(modif_keyset, 0, 256);
}
/*****************************************************************************/
/* setup_macros */
/*****************************************************************************/
// A_2704
// double checked
void setup_macros(uint16_t eeaddr, uint8_t macros)
{
uint8_t i, b1, b2;
uint8_t *p = macro_data + (macro_cnt * 5);
// A_272c
for (i = 0; i < macros; i++, p += 5)
{
// A_2734
if (macro_cnt == allocated_macros /*R9*/)
return;
// A_2746
p[0] = eeprom_read_byte((const uint8_t *)eeaddr);
// A_275c
p[1] = eeprom_read_byte((const uint8_t *)(eeaddr + 1));
// A_2766
p[2] = eeprom_read_byte((const uint8_t *)(eeaddr + 2));
// A_2776
*(uint16_t*)(p + 3) = eeaddr + 3;
b1 = eeprom_read_byte((const uint8_t *)(eeaddr + 3)) & 0x3f;
// A_278a
b2 = eeprom_read_byte((const uint8_t *)(eeaddr + 4)) & 0x3f;
// A_279e
// written this way to prevent avrgcc using 16bit calculations
b1 += b2;
b1 += b1;
b1 += 5; // macro header
eeaddr += b1; // skip additional data
// A_27a6
macro_cnt++;
// A_27ae
}
}
/*****************************************************************************/
/* alloc_macros : allocate space for macros on heap */
/*****************************************************************************/
// A_27ce
// double checked
uint8_t alloc_macros(uint8_t count, uint8_t allocbase)
{
if (allocbase)
{
modif_keyset = (uint8_t*)memalloc(256);
reset_modifset();
}
// A_27e8
macro_data = (uint8_t*)memalloc(count * 5);
if (!macro_data)
return 0;
// A_2804
allocated_macros = count;
macro_cnt = 0;
return 1;
}
/*****************************************************************************/
/* exec_macro */
/*****************************************************************************/
// A_2812
// fairly sure
void exec_macro(uint16_t eeaddr, uint8_t modif_set, uint8_t make)
{
uint8_t i;
uint8_t b1, b2, restoremeta;
b1 = eeprom_read_byte((const uint8_t*)eeaddr++);
// could be time-optimized, since b2 is only needed if !make
b2 = eeprom_read_byte((const uint8_t*)eeaddr++);
// A_283c
b1 &= 0x3f;
restoremeta = b2 & 0x80;
// R24 = R15 & 0x3f;
if (make) // if key is pressed,
i = b1; // use the make macro part
else // otherwise
{
// A_2848
i = b2 & 0x3f; // use the onbreak macro part
b1 += b1; // so skip behind the make macro part
eeaddr += b1;
if (restoremeta) // if norestoremeta is NOT given
// A_285c
queue_key(MCMD_PUSH_META | MCMD_ASSIGN_META, modif_set);
}
// A_2864
for (; i != 0; i--) // queue macro commands
{
b1 = eeprom_read_byte((const uint8_t*)eeaddr++);
b2 = eeprom_read_byte((const uint8_t*)eeaddr++);
queue_key(b1, b2);
}
// A_2882 if break and norestoremeta is NOT given
if (!make && restoremeta)
queue_key(MCMD_POP_META, 0);
}
/*****************************************************************************/
/* find_exec_macro */
/*****************************************************************************/
// A_28a4
// double checked
uint8_t find_exec_macro(uint8_t keyid, uint8_t make)
{
uint8_t modif_set = modif_curset;
uint8_t rc;
uint16_t eeaddr;
if (modif_keyset)
{
// A_28be
if (make)
// A_28c2
modif_keyset[keyid] = modif_set;
// An "else" would be appropriate. Not in original, but here...
else
// A_28c8
modif_set = modif_keyset[keyid];
}
// A_28d6
if (setup_done &&
// A_28de
(eeaddr = find_macro(keyid, modif_set)) != 0)
{
// A_28e8
exec_macro(eeaddr, modif_set, make);
rc = 1;
}
else
// A_28f2
rc = 0;
// A_28f4
if (IS_MODIFIER_KEY(keyid))
{
// A_2904
if (make)
// A_2910
modif_curset |= (1 << (keyid & 0x07));
else
// A_2922
modif_curset &= ~(1 << (keyid & 0x07));
}
return rc;
}
/*****************************************************************************/
/* eeprom_write_ready : returns whether NOT writing buffer to EEPROM ATM */
/*****************************************************************************/
// A_2942
uint8_t eeprom_write_ready(void)
{
return !writing_eeprom_buffer;
}
/*****************************************************************************/
/* write_eeprom_buffer : triggers writing buffer to EEPROM, interrupt-based */
/*****************************************************************************/
// A_2952
// double checked
int8_t write_eeprom_buffer(uint8_t *wbuf, uint16_t eeaddr, uint8_t cnt)
{
eeprom_write_flag = 1;
if (writing_eeprom_buffer)
return -1;
if (EECR & (1 << EEPE))
return -2;
eeprom_write_eeaddr = eeaddr;
eeprom_write_buffer = wbuf;
eeprom_write_cnt = cnt;
writing_eeprom_buffer = 1;
EECR |= (1 << EERIE);
return 0;
}
/*****************************************************************************/
/* EE_READY_vect : EEPROM ready interrupt */
/*****************************************************************************/
// A_298c
// double checked (except for register)
ISR(EE_READY_vect)
{
uint16_t weea;
if (!eeprom_write_cnt)
{
// A_2a00
EECR &= ~(1 << EERIE);
writing_eeprom_buffer = 0;
return;
}
// A_29b6
if (eeprom_write_flag)
{
// A_29be
// skip all EEPROM bytes equal to the write buffer contents
while (eeprom_read_byte((const uint8_t *)eeprom_write_eeaddr) ==
*eeprom_write_buffer)
{
// A_29ca
eeprom_write_buffer++;
eeprom_write_eeaddr++;
if (!--eeprom_write_cnt)
{
// A_2a00
EECR &= ~(1 << EERIE);
writing_eeprom_buffer = 0;
return;
}
// A_2a08
}
}
// A_2a22
// use local var to prohibit reload for EEARH / EEARL loading from volatile
weea = eeprom_write_eeaddr;
EEARH = (weea >> 8);
EEARL = (weea & 0xff);
EEDR = *eeprom_write_buffer;
EECR |= (1 << EEMPE);
EECR |= (1 << EEPE);
eeprom_write_cnt--;
eeprom_write_buffer++;
eeprom_write_eeaddr++;
}
/*****************************************************************************/
/* _BL_ADDR : get the boot loader indirect call address */
/*****************************************************************************/
// should work for all devices with 16 bit PC
#define _BL_ADDR(blsz_w) ( (uint16_t)((FLASHEND >> 1) + 1) - (blsz_w))
/*****************************************************************************/
/* jmp_bootloader : guess what */
/*****************************************************************************/
// A_2a8e
// double checked
void jmp_bootloader(void)
{
uint16_t bootsz;
typedef void (*tBootLdr)(void) __attribute__((noreturn));
uint8_t fbits = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
if (fbits & ~FUSE_HWBE) // if HWBE unprogrammed
return; // don't even TRY to go to boot loader :-)
// slightly adapted from http://www.pjrc.com/teensy/jump_to_bootloader.html
cli();
UDCON = (1 << DETACH);
USBCON = (1 << FRZCLK);
UCSR1B = 0;
_delay_ms(5);
#if defined(__AVR_AT90USB162__) // Teensy 1.0
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
DDRB = 0; DDRC = 0; DDRD = 0;
PORTB = 0; PORTC = 0; PORTD = 0;
#elif defined(__AVR_ATmega32U4__) // Teensy 2.0 etc.
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#elif defined(__AVR_AT90USB646__) // Teensy++ 1.0
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#endif
// get Boot Size fuse bits
fbits = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
fbits = ((fbits & (~FUSE_BOOTSZ1 | ~FUSE_BOOTSZ0)) >> 1) ^ 0x03;
// calculate boot loader size in WORDS
for (bootsz = 256; fbits; fbits--)
bootsz *= 2;
// Off we go...
((tBootLdr)_BL_ADDR(bootsz))();
}
/*****************************************************************************/
/* setup_proc_kbd : */
/*****************************************************************************/
// A_2b22
// double checked
void setup_proc_kbd(uint8_t keyboard_codeset, uint16_t keyboard_id)
{
proc_keyboard_codeset = keyboard_codeset;
proc_keyboard_id = keyboard_id;
}
/*****************************************************************************/
/* process_select */
/*****************************************************************************/
// A_2b30
// double checked
void process_select(uint8_t hidx)
{
hidx -= KEY_SELECT_0; // 0xd8 .. 0xdf (Select Reset .. Select 7 Toggle)
if (hidx)
// A_2b36
req_select_set ^= (1 << hidx);
else
// A_2b50
req_select_set = 1;
}
/*****************************************************************************/
/* check_eeprom_header : check for 'SC' at the start of the EEPROM data */
/*****************************************************************************/
// A_2b58
// double checked
uint8_t check_eeprom_header(void)
{
// Writing it as
// return (eeprom_read_byte((const uint8_t *)0) == 'S' &&
// eeprom_read_byte((const uint8_t *)1) == 'C');
// (functionally equivalent) gives inefficient avr-gcc assembler output
if (eeprom_read_byte((const uint8_t *)0) == 'S' &&
eeprom_read_byte((const uint8_t *)1) == 'C')
return 1;
return 0;
}
/*****************************************************************************/
/* get_forced_keyboard_type : returns forced keyboard type from EEPROM */
/*****************************************************************************/
// A_2b7e
// double checked
uint8_t get_forced_keyboard_type(void)
{
uint16_t eecnt;
if (!check_eeprom_header())
return 0;
eecnt = eeprom_read_word((const uint16_t *)2);
if (!eecnt ||
eecnt >= (E2END - 7) ||
eeprom_read_byte((const uint8_t *)4) != 1)
return 0;
return eeprom_read_byte((const uint8_t *)6);
}
/*****************************************************************************/
/* count_macro_onbreaks */
/*****************************************************************************/
// A_2baa
// looks like a sanity check over the EEPROM that counts all
// tuples which have a count in the 5th byte
// double checked
uint8_t count_macro_onbreaks(uint16_t eeaddr, uint8_t macros, uint8_t bcnt)
{
uint8_t i, b1, b2;
uint8_t addd;
for (i = 0; i < macros; i++)
{
// A_2bbe
if (bcnt < 5) /* bad end count */
return 0;
b1 = eeprom_read_byte((const uint8_t *)eeaddr + 3) & 0x3f;
b2 = eeprom_read_byte((const uint8_t *)eeaddr + 4) & 0x3f;
if (b2) // onbreak?
// A_2bd6
macro_onbreaks++;
// A_2be0
// written this way instead of
// addd = ((b1 + b2) * 2) + 5;
// to prevent avt-gcc using 16 bit arithmetic
addd = b1 + b2;
addd += addd;
addd += 5;
if (bcnt < addd)
return 0;
// A_2bf0
eeaddr += addd;
bcnt -= addd;
// A_2bfc
}
// A_2c02
return 1;
}
/*****************************************************************************/
/* init_eeprom_header */
/*****************************************************************************/
// A_2c16
// double checked
void init_eeprom_header(void)
{
eeprom_write_byte((uint8_t *)3, 0);
eeprom_write_byte((uint8_t *)2, 0);
eeprom_write_byte((uint8_t *)1, 'C');
eeprom_write_byte((uint8_t *)0, 'S');
}
/*****************************************************************************/
/* setup_eeprom_header */
/*****************************************************************************/
// A_2c36
// double checked
void setup_eeprom_header(void)
{
if (!check_eeprom_header())
init_eeprom_header();
}
/*****************************************************************************/
/* load_from_ee : tests or loads config from EEPROM */
/*****************************************************************************/
// A_2c40
uint8_t load_from_ee(uint16_t eeaddr, uint8_t cnt, uint8_t do_setup)
{
uint8_t b2; // 2nd byte
uint8_t b2type;
uint8_t b2select;
eeaddr++; // skip 1st byte (already in cnt)
b2 = eeprom_read_byte((const uint8_t *)eeaddr);
b2type = b2 & 0x07;
if (!do_setup)
{
// A_2c68
switch(b2type)
{
case 0 :
print_P(PSTR("layers "));
break;
case 1 :
print_P(PSTR("remaps "));
break;
case 2 :
print_P(PSTR("macros "));
break;
}
}
// A_2c88
// R2021 = b2;
// R1819 = req_select_set;
// R2425 = (b2 & 0x38) >> 3;
// A_2ca2
// R18 = (req_select_set >> ((b2 & 0x38) >> 3));
// A_2cac
// written this way to prevent avr-gcc using 16bit arithmetic
b2select = b2 & 0x38;
b2select >>= 3;
if (!((req_select_set >> b2select) & 1))
{
// A_2cb0
if (!do_setup)
// A_2cb6
print_P(PSTR("!select "));
return 1;
}
// A_2cbc
eeaddr++;
cnt -= 2;
if (b2 & 0x40) // bit 6 = followed by codeset bitset
{
// A_2cc8
uint8_t codesets = eeprom_read_byte((const uint8_t *)eeaddr);
codesets >>= (proc_keyboard_codeset - 1);
if (!(codesets & 1))
{
// A_2ce6
if (!do_setup)
print_P(PSTR("!set "));
return 1; // not sure whether this is correct... it's an error...
}
// A_2cf2
eeaddr++;
cnt--;
}
// A_2cfa
if (b2 & 0x80) // bit 7 = followed by keyboard_id word
{
// A_2cfe
if (eeprom_read_word((const uint16_t *)eeaddr) != proc_keyboard_id)
{
// A_2d10
if (!do_setup)
print_P(PSTR("!id "));
return 1; // not sure whether this is correct... it's an error...
}
// A_2d1e
eeaddr += 2;
cnt -= 2;
}
// A_2d24
if (b2type == 1) // remaps
{
// A_2da0:
uint8_t layer = eeprom_read_byte((const uint8_t *)eeaddr);
uint8_t rcnt = eeprom_read_byte((const uint8_t *)eeaddr + 1);
cnt -= 2;
if (rcnt * 2 != cnt)
{
// A_2dc6
print_P(PSTR("error "));
return 0;
}
// A_2dcc
if (do_setup)
// A_2dd0
read_remap(eeaddr + 2, rcnt, layer);
return 1;
}
// A_2d2a
else if (b2type == 0) // layers
{
// A_2d36:
uint8_t lcnt = eeprom_read_byte((const uint8_t*)eeaddr);
uint8_t i;
cnt--;
if (lcnt * 2 != cnt)
{
// A_2d52
print_P(PSTR("error "));
return 0;
}
// A_2d58
if (!do_setup)
// A_2d5c
layerdefs += lcnt;
// A_2d66
eeaddr++;
for (i = 0; i < lcnt; i++)
{
// A_2d6e
uint8_t keyid = eeprom_read_byte((const uint8_t *)eeaddr); // keyid? Sure?
uint8_t layer = eeprom_read_byte((const uint8_t *)eeaddr + 1);
if (do_setup)
// A_2d80
setup_layer(keyid, layer);
else
{
// A_2d86
if (max_layer < layer)
max_layer = layer;
}
// A_2d92
eeaddr += 2;
// A_2d94
}
return 1;
}
else if (b2type == 2) // macros
{
// A_2dda:
uint8_t macros = eeprom_read_byte((const uint8_t *)eeaddr++);
if (do_setup)
{
// A_2dea
setup_macros(eeaddr, macros);
return 1;
}
// A_2df2
if (!count_macro_onbreaks(eeaddr, macros, cnt))
{
// A_2dfe
print_P(PSTR("error "));
return 0;
}
// A_2e08
total_macros += macros;
return 1;
}
else
return 0;
}
/*****************************************************************************/
/* setup_processing */
/*****************************************************************************/
// A_2e28
uint8_t setup_processing(void)
{
uint16_t eeaddr; /* EEPROM start address to read from */
int16_t eecnt; /* (remaining) EEPROM data bytes */
uint8_t scnt;
jmp_reset_macro_data();
reset_layer_trans();
memreset();
layerdefs = 0;
max_layer = 0;
total_macros = 0;
macro_onbreaks = 0;
if (!check_eeprom_header())
return 0;
// A_2e54
eecnt = eeprom_read_word((const uint16_t *)2) - 4;
print_P(PSTR("\n\nremaining: "));
phex16(eecnt);
usb_debug_putchar('\n');
// A_2e7a
if (eecnt < 1 || eecnt > E2END - 9) // 8 bytes for header, 2 for ...?
return 0;
// If a new version can read old EEPROM contents, this needs a rewrite
if (eeprom_read_byte((const uint8_t *)4) != SETTINGS_VER ||
eeprom_read_byte((const uint8_t *)5) > SETTINGS_SUBVER)
return 0;
for (eeaddr = 8; eecnt > 0; eeaddr += scnt, eecnt -= scnt)
{
scnt = eeprom_read_byte((const uint8_t *)eeaddr);
phex(scnt);
usb_debug_putchar('@');
phex16(eeaddr);
usb_debug_putchar(' ');
if (scnt < 5)
{
print_P(PSTR("len<5\n"));
return 0;
}
// A_2ebe
if (!load_from_ee(eeaddr, scnt, 0))
{
print_P(PSTR("!apply\n"));