-
Notifications
You must be signed in to change notification settings - Fork 2
/
iv7_1_0.ino
2525 lines (2303 loc) · 85.2 KB
/
iv7_1_0.ino
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
/*
____________________
Welcome to Ivee (IV7) - A Powerful Programable RPN Calculator based on FORTH
Version 1.0, (c) 2020 by deetee/zooxo
This software is covered by the 3-clause BSD license.
See also: https://youtu.be/uZYgRxXX5ro
____________________
____________________
PREAMBLE
____________________
IV7 is a port of IVEE (see https://github.com/zooxo/iv) to the QYF-TM1638
development board. The most obvious difference to IVEE and its matrix display
is the old fashioned 8 digit 7 segment display of the QYF-Board. So no plots
are possible, there is no business calculator and the representation of text
(ie sorted FORTH commands) is very limited. On the other hand there was space
left to implement a convenient matrix mode.
Nevertheless IV7 offers nearly the same range of functionality like IVEE:
- 120 intrinsic functions based on FORTH
- Programming: Handle up to 40 user definable programs
(Edit, New, Rename, Move, Delete, Send, Load)
- Dictionary of all commands, words and programs
- Fast user definable menu (longpressed F-key)
- Calculations with complex numbers for nearly every function
- Calculus (f(x), solve, integrate)
- Basic math operations in number systems with selectable BASE
- Save up to 10 numbers/constants permanently
- Statistics and line best fit
- Matrix mode to calculate (complex) matrices
- Many unit conversions
- Clock function
- Basic system functions (Battery voltage, Brightness, Screensaver)
Have fun!
deetee
____________________
KEYBOARD, CODES
____________________
F(G)[OFF]{MENU} 7(SUM+)[SUMCLR] 8(PRG)[FREE] 9(/)[MAT]
E(SWAP)[ROT] 4(DICT)[USR] 5(FX)[BASE] 6(*)[TXT]
N(OVER)[PICK] 1(RCL)[STO] 2(FSOLV)[FINT] 3(-)[LIT-]
X(CLR)[TOFF] 0(CPLX)[] .(CVIEW)[CLK] #(+)[LIT+]
PRG Shortcuts: BASE/HEX Shortcuts:
E UP 5 OUT 6 UP E EXIT 4 E 5 F
N DOWN 1 NEW 2 IN 3 DOWN 1 B 2 C 3 D
X EXIT 0 REN . DEL D EDIT X CLR 0 A . A~F
MENU/DICT/REN Navigation:
A B C D A: NUMERIC, MATH
UP E 4 5 6 B: TRIG/HYP, STAT/LR, CPLX, BASE, FN, LOGIC, SYSTM
DOWN N 1 2 3 C: STACK, PRG, CONVERT
PREV0 .NEXT D: USERPRGS
BUTTONCODES (used by GETKEY): SUM/STAT/L.R. Storage Registers:
F(15) 7(07) 8(08) 9(09) 7 SN 8 SX 9 SY
E(14) 4(04) 5(05) 6(06) 5 SXX 6 SXY
N(13) 1(01) 2(02) 3(03)
X(12) 0(00) .(10) #(11)
MATRIX
F(OP) 7[1|1] 8[1|2] 9[1|3](INV)
E[A<->B](SWAP) 4[2|1] 5[2|2] 6[2|3](A*B)
N[POP<->VIEW](COPY) 1[3|1] 2[3|2] 3[3|3](A-B)
X[EXIT](CLR) 0[FLUSH](TRANS) .[LOAD](DET) #[PUSH](A+B)
____________________
DISPLAY, INDICATORS
____________________
_ _ Prompt (regular and base mode)
_
_ . |. Numeric mode (F-key, G-key, number input, stack floated)
| | Complex mode (rectangular, polar)
_
| |
| | |_ Complex view (real, imaginary, absolute, angle)
_ _
|_| |_
| |_ Program mode (select, edit)
| |
| | . Matrix mode (A, B, view)
____________________
COMPLEX VIEW
____________________
Use CVIEW and the cursor keys "E" or "0" respective "N" or "." to view the
components of a complex number (real part, imaginary part, absolute value
or angle). Note that the complex indicator indicates the viewed component:
_
| (real), | (imaginary), | | (absolute value) or |_ (angle)
If you want to make ongoing calculations with one component press enter to
copy the desired component to the stack. Note that the original complex
number will be removed from the stack.
Escape the complex viewing mode with "X".
Like in IVEE the function CPLX is used to convert the stack to a complex
number and vice versa. If the rectangular or polar mode is used shows the
complex indicator (left or right comma). The used mode can be set by
escaping the complex view mode either when viewing the rectangular
(real/imaginary) or when viewing the polar (absolute/angle) components.
____________________
MATRIX
____________________
Despite of the simple display IV7 offers many functions for convenient
dealing with (complex) 3x3-matrices. Possible operations are adding,
substracting or multiplying matrices, calculating the inverse, transpose or
determinant or moving data from the stack to a matrix and vice versa.
After entering the matrix mode with "MAT" (F-9) you can toggle between
matrix A and B (indicated with high or low quotation marks) with E as well
as toggle between view mode (indicated with a dot) or STO-mode. When in
store mode the displayed stack value can be stored to the appropriate
position in the matrix with 789, 456 or 123.
For instance to store 1.5 to row 2 and column 3 of matrix B enter 1.5 to
the stack, enter the matrix mode (F-9), toggle to matrix B ("E", indicates
low quotation marks) and press 6 (row 2 and column 3).
To view matrix values toggle with "N" to view mode ("."-indicator) and
select the appropriate location of the matrix element (ie "7" for the
0|0-location).
Please note that it is possible to load the whole matrix from stack
(9 "reverse" entered values) with "." or to flush all matrix values to stack
with "0". Loading an empty stack clears the whole matrix (like F-X).
To copy a matrix (A to B or vice versa) press F-N.
To examine one value of the matrix (ie for viewing the imaginary part) view
it and push it with "#" to the stack.
Operations like A=A+B can be done with F-#.
Please note that matrix functions are neither programable nor selectable
from the dictionary.
To exit the matrix mode press "X".
____________________
PROGRAMMING
____________________
Example program to query button code (inclusive displaying text):
tC // Clear text register
127 tP 28 tP 120 tP 120 tP 92 tP 84 tP // Write "Button" to text register
tS // Show text register
1 PS // Pause for 1 quarter second
KY // Query button code
____________________
DICTIONARY
____________________
Numerics (cursor keys E and N)
_ _ _
| | | _| _|
|_| 0 | 1 |_ 2 _| 3
_ _ _
|_| |_ |_ |
| 4 _| 5 |_| 6 | 7
_ _
|_| |_| _
|_| 8 _| 9 . . NEGATE
_ _ _ _
|_ |_ |_| | _ _ |_ |_
|_ |_ EE | | PI | |_ RCL _| |_ STO
Mathematics
_ _ _
|_| _| ADD |_ |_ SUB | | MULT _| DIV
| | |_| + _| |_| - | | |_| * |_| | /
_
_| | | _ _
| | |_| MOD | | ABS . INT . FRAC
_ _ _ _
|_ | _ |_| |_| | |
|_ EXP |_ | | LN | _ POW10 |_ |_| LOG
_ _ _
| | | |_| | | LN
| SQRT | INV | POW |_ | (GAMMA)
_ _ _ _
| | | |_| |_ _| _| _| DELTA
|_ |_| COMB | |_ PERM | % |_| | %
_ _ _
|_| |_| _ _| |_| |_ _| _
| | PV | | |_| ND | |_ QE |_|.| DEG.RAD
Trigonometrics/Hyperbolics (cursor keys 4 and 1)
_ _ _
|_ | |_ |_
_| SIN |_ COS |_ TAN _|. ASIN
_ _ _
| |_ |_ |_ HYP |_ | HYP
|_ . ACOS |_ . ATAN | | _| SIN | | |_ COS
_ _
|_ |_ HYP |_ |_ AHYP |_ | AHYP |_ |_ AHYP
| | |_ TAN | | _|. SIN | | |_ . COS | | |_ TAN
Statistics. Linear Regression
_ _ _ _ _
|_ _ |_ |_| |_ |_
_| |_ SUMCLR _| | | SUM+ _| _| SUM-
_
_ | _
|_| STAT |_ | L.R.
Complex, Base
_ _ _ _ _
| | |_| COMPLEX |_ |_| |_ |_
|_ COMPLEX |_ VIEW |_| | | BASE | | |_ HEX
Function
_ _ _ _
|_ _ |_ |_ FN |_ | FN
| | | FN | _| SOLVE | | INT
Logics
_ _
BINARY _ |_ LOGIC |_| _ LOGIC _ _ LOGIC
NOT | | |_ NOT | | | | AND |_| | OR
System
_ _
_| _ |_ _ |_ |_ _ OFF
|_| |_ DICT |_| _| USER |_| | OFF |_ |_| TIME
_ _
|_ |_ | LIT | _| LIT | |_
|_| |_ BATT |_ |_| UP |_ |_| DOWN |_ | | CLOCK
Stack (cursor keys 5 and 2)
_
_ | CLEAR _| _| _ |_ | |
|_ |_ ALL |_| |_| DUP |_| | DROP _| _ SWAP
_ _ _
_ _ _ |_| |_| _ |_| |_ PRG
| |_| ROT |_| | OVER | |_ PICK | | FREE
Programming
_ _
|_| _ _| @ | ! _|
| | PRG |_| POKE . PEEK EXE
_ _ _
|_ |_| ADD |_| |_
|_ | | TIME | _| PAUSE
_ _ _ _
|_ |_| GET |_ | TEXT |_ |_| TEXT |_ |_ TEXT
| | _| KEY |_ |_ CLEAR |_ | PRINT |_ _| SHOW
LESS _ _ NOT GREATER
|_ THAN _ EQUAL _ . EQUAL _| THAN
_ _ _
_ _| IS |_ |_ | |_ |_
| | REAL? | | IF |_ |_ ELSE |_ | | THEN
_
|_ |_ _ |_ _
|_| |_ BEGIN |_| | | UNTIL |_| | BREAK
Conversions
_ _
_ |_ |_ _ |_ | | |
| | HMS->H | | H->HMS | |.|_ KG-LBS |_ .|_| L-GAL
_ _ _ _ _ _
| |_ |_ |_ _
|_ .| C-F | |.| | KM-MI | |.| M-FT |_ .| CM-IN
____________________
7-SEGMENT DISPLAY
____________________
--a-- hgfe-dcba 8421-8421
| |
f b Example code to display "3": abcdg = 0400-8421 = 0x4f = 79
|--g--|
e c
| |
--d-- (h)
DEC 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
HEX 0 1 2 3 4 5 6 7 8 9 a b c d e f
_ _ _ _ _ _ _ _
| | | | | | | |
000 00 | | | | _ _ _ _ _| _| _| _|
_ _ _ _ _ _ _ _
| | | | | | | |
016 10 | | | | | | | | | | | | |_ |_ |_ |_ |_| |_| |_| |_|
_ _ _ _ _ _ _ _
| | | | | | | | | | | | | | | | | | | | | | | |
032 20 | | | | _ _ _ _ _| _| _| _|
_ _ _ _ _ _ _ _
| | | | | | | | | | | | | | | | | | | | | | | |
048 30 | | | | | | | | | | | | |_ |_ |_ |_ |_| |_| |_| |_|
_ _ _ _ _ _ _ _
_ _ _| _| _ _ _| _| _ _ _| _| _ _ _| _|
064 40 | | | | _ _ _ _ _| _| _| _|
_ _ _ _ _ _ _ _
_ _ _| _| _ _ _| _| _ _ _| _| _ _ _| _|
080 50 | | | | | | | | | | | | |_ |_ |_ |_ |_| |_| |_| |_|
_ _ _ _ _ _ _
|_ |_ |_| |_| |_ |_ |_| |_| |_ |_ |_| |_| |_ |_ |_| |_|
096 60 | | | | _ _ _ _ _| _| _| _|
_ _ _ _ _ _ _ _
|_ |_ |_| |_| |_ |_ |_| |_| |_ |_ |_| |_| |_ |_ |_| |_|
112 70 | | | | | | | | | | | | |_ |_ |_ |_ |_| |_| |_| |_|
____________________
CIRCUIT DIAGRAM
____________________
_______/ _______
| OnOff-Switch |
| __________ | _________________
| | | | _USB_ | 8.8.8.8.8.8.8.8.|
+----+--|BATT+ IN+|--+---VCC-| |-GND--GND-|GND |
_|_ | | | 3|----------|DIO * * * |
= | | | 6|----------|CLK * * * |
+-------|BATT- IN-|------GND-| 9|----------|STB * * * |
|__________| |_____|-VCC--VCC-|VCC * * * |
LIPO LIPO Battery Arduino |_________________|
Battery Charger Pro Micro QYF-TM1638
(TP4056)
*/
// INCLUDES
#include <EEPROM.h>
#include <avr/power.h> // Needed for power management
#include <avr/sleep.h> // Needed for sleeping
// PINS
#define STROBE 9 // Strobe pin // Arduino/Genuino Micro
//#define STROBE 11 // Strobe pin // Mini
#define CLOCK 6 // Clock pin
#define DATA 3 // Data pin
// COMMANDS (QYF-TM1638-board)
#define PRINTCMD 0x40 // Command code for display printing
#define READCMD 0x42 // Command code for key reading
// POWER SAVING
static byte eachframemillis, thisframestart, lastframedurationms; // Framing times
static boolean justrendered; // True if frame was just rendered
static void idle(void) { // Idle, while waiting for next frame
SMCR = _BV(SE); // Select idle mode and enable sleeping
sleep_cpu();
SMCR = 0; // Disable sleeping
}
static bool nextFrame(void) { // Wait (idle) for next frame
byte now = (byte) millis(), framedurationms = now - thisframestart;
if (justrendered) {
lastframedurationms = framedurationms;
justrendered = false;
return false;
}
else if (framedurationms < eachframemillis) {
if (++framedurationms < eachframemillis) idle();
return false;
}
justrendered = true;
thisframestart = now;
return true;
}
// CONSTANTS
#define DIGITS 8 // Number of digits
#define SEGMENTS 8 // Number of segments per digit
#define KEYS 16 // Number of keys
#define FRAMERATE 15 // Maximal number of screen refreshes per second (>3)
#define EEBRIGHTNESS 0 // EEPROM address for brightness
#define END 255 // Escape key
#define DARKTIMEMIN 2 // Minimal time for auto display off in 10 x s
// KEY VALUES
#define _KF 15 // key number: getkey(): keycast[]: symbol:
#define _K7 7 // 1 2 3 4 1 3 5 7 15 7 8 9 F 7 8 9
#define _K8 8 // 5 6 7 8 9 11 13 15 14 4 5 6 E 4 5 6
#define _K9 9 // 9 10 11 12 16 2 4 6 13 1 2 3 N 1 2 3
#define _KE 14 // 13 14 15 16 8 10 12 14 12 0 10 11 X 0 D P
#define _K4 4
#define _K5 5
#define _K6 6
#define _KN 13
#define _K1 1
#define _K2 2
#define _K3 3
#define _KX 12
#define _K0 0
#define _KD 10
#define _KP 11
// SIGN
#define _70 0x3f // --a-- hgfe-dcba 8421-8421
#define _71 0x06 // | |
#define _72 0x5b // f b
#define _73 0x4f // |--g--|
#define _74 0x66 // e c
#define _75 0x6d // | |
#define _76 0x7d // --d-- (h)
#define _77 0x07
#define _78 0x7f
#define _79 0x6f
#define _7Q 0x3b
#define _7A 0x77
#define _7b 0x7c
#define _7C 0x39
#define _7c 0x58
#define _7d 0x5e
#define _7E 0x79
#define _7F 0x71
#define _7G 0x3d
#define _7h 0x74
#define _7H 0x76
#define _7i 0x04
#define _7I 0x30
#define _7J 0x0e
#define _7j 0x0d
#define _7K 0x75
#define _7L 0x38
#define _7N 0x37
#define _7n 0x54
#define _7M 0x15
#define _7o 0x5c
#define _7P 0x73
#define _7Q 0x3b
#define _7q 0x67
#define _7R 0x31
#define _7r 0x50
#define _7S 0x6d
#define _7t 0x78
#define _7u 0x1c
#define _7U 0x3e
#define _7V 0x72
#define _7W 0x2a
#define _7y 0x6e
#define _7ABSOLUTE 0x36
#define _7APOSTROPHELEFT 0x20
#define _7APOSTROPHERIGHT 0x02
#define _7AT 0x5f
#define _7COMMALEFT 0x10
#define _7COMMARIGHT 0x04
#define _7Cabs 0x14
#define _7Cre 0x21 // Imaginary indicators
#define _7Cim 0x02
#define _7Cangle 0x18
#define _7DEGREE 0x63
#define _7DOT 0x80
#define _7DOWN 0x0c
#define _7ENTER 0x42
#define _7EQUAL 0x48
#define _7GAMMA 0x31
#define _7GRAD 0x63
#define _7GREATERTHAN 0x0c
#define _7HIGHEQUALSIGN 0x41
#define _7HIGHLINE 0x01
#define _7LEFTBRACKET 0x39
#define _7LESSTHAN 0x18
#define _7LOWLINE 0x08
#define _7LOWHIGHLINE 0x09
#define _7MATA 0x22
#define _7MATB 0x14
#define _7MINUS 0x40
#define _7QUESTIONMARK 0x53
#define _7QUOTATIONMARK 0x22
#define _7PARALLEL 0x36
#define _7RECORD 0x6b
#define _7REVERSESOLIDUS 0x64
#define _7RIGHTBRACKET 0x0f
#define _7SOLIDUS 0x52
#define _7SPACE 0x00
#define _7SQRT 0x33
#define _7STATISTIC 0x5d
#define _7SWAP 0x1b
#define _7TEN 0x6b
#define _7THREELINES 0x49
#define _7UP 0x03
static const byte digit[] = // Digits
{ _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7A, _7b, _7c, _7d, _7E, _7F};
#define MAXCMDI 76 // Number of commands of intrinsic functions
#define MAXCMDB 120 //120 End of builtin commands
#define MAXCMDU 160 //160 End of user commands
static byte msgnr = 0; // MESSAGES
#define MSGASK 0
#define MSGERROR 1
const char m0[] PROGMEM = {_7QUESTIONMARK, NULL};
const char m1[] PROGMEM = {_7E, _7r, _7r, _7o, _7r, NULL};
const char* const msg[] PROGMEM = {m0, m1};
// Command code defines
#define _0 0 // Intrinsic commands
#define _1 1
#define _2 2
#define _3 3
#define _4 4
#define _5 5
#define _6 6
#define _7 7
#define _8 8
#define _9 9
#define _DOT 10
#define _DUP 11
#define _DROP 12
#define _NEG 13
#define _E 14
#define _CMPLX 16
#define _RCL 17
#define _SUB 19
#define _MULT 22
#define _DIV 25
#define _ADD 27
#define _SWAP 30
#define _STO 33
#define _BASE 37
#define _PICK 45
#define _ROT 46
#define _LT 48
#define _EQ 49
#define _NE 50
#define _GT 51
#define _NAND 52
#define _ADDDUR 53
#define _PAUSE 54
#define _INT 55
#define _BEGIN 58
#define _UNTIL 59
#define _IF 61
#define _ELSE 62
#define _THEN 63
#define _ISREAL 68
#define _PI 71
#define _INV 72
#define _SIN 73
#define _EXP 74
#define _LN 75
#define _MOD MAXCMDI+0 // Builtin commands (mem)
#define _HEX MAXCMDI+1
#define _AND MAXCMDI+2
#define _NOT MAXCMDI+3
#define _OR MAXCMDI+4
#define _OVER MAXCMDI+5
#define _ABS MAXCMDI+6
#define _SQRT MAXCMDI+7
#define _COS MAXCMDI+8
#define _TAN MAXCMDI+9
#define _POW MAXCMDI+10
#define _PWR10 MAXCMDI+11
#define _LOG MAXCMDI+12
#define _ASIN MAXCMDI+13
#define _ACOS MAXCMDI+14
#define _ATAN MAXCMDI+15
#define _SINH MAXCMDI+16
#define _COSH MAXCMDI+17
#define _TANH MAXCMDI+18
#define _ASINH MAXCMDI+19
#define _ACOSH MAXCMDI+20
#define _ATANH MAXCMDI+21
#define _GAMMALN MAXCMDI+22
#define _HMS2H MAXCMDI+23
#define _H2HMS MAXCMDI+24
#define _PV MAXCMDI+25
#define _ND MAXCMDI+26
#define _QE MAXCMDI+27
#define _CLOCK MAXCMDI+28
#define _CLRSUM MAXCMDI+29
#define _SUM MAXCMDI+30
#define _SUMSUB MAXCMDI+31
#define _STAT MAXCMDI+32
#define _LR MAXCMDI+33
#define _PERCENT MAXCMDI+34
#define _PERCENTDELTA MAXCMDI+35
#define _FRAC MAXCMDI+36
#define _DEGRAD MAXCMDI+37
#define _CF MAXCMDI+38
#define _KMMI MAXCMDI+39
#define _MFT MAXCMDI+40
#define _CMIN MAXCMDI+41
#define _KGLBS MAXCMDI+42
#define _LGAL MAXCMDI+43
#define _PREEND 254 // Function delimiter
#define _END 255 // Function delimiter
// Builtin functions (mem)
const byte mem[] PROGMEM = {
_END, // Necessary to prevent function starting with mp = 0
//_1, _0, _BASE, _END, //0 BUSINESS
_SWAP, _DUP, _ROT, _DUP, _ROT, _SWAP, _DIV, _INT, _MULT, _SUB, _END, //0 MODULO
_1, _6, _BASE, _END, //1 HEX
_NAND, _DUP, _NAND, _END, //2 AND
_DUP, _NAND, _END, //3 NOT
_DUP, _NAND, _SWAP, _DUP, _NAND, _NAND, _END, //4 OR
_SWAP, _DUP, _ROT, _ROT, _END, //5 OVER
_DUP, _0, _LT, _IF, _NEG, _THEN, _END, //6 ABS
_DUP, _0, _EQ, _IF, _DROP, _0, _ELSE, _LN, _2, _DIV, _EXP, _THEN, _END, //7 SQRT sqrt(z)=exp(2*ln(z))
_ISREAL, _1, _EQ, _IF, _9, _0, _SWAP, _SUB, _ELSE, _PI, _2, _DIV, _ADD, _THEN, _SIN, _END, //8 COS cos(x)=sqrt(1-sin(z)*sin(z)) cos(x)=sin(90-x)
_DUP, _SIN, _SWAP, _COS, _DIV, _END, //9 TAN tan(z)=sin(z)/cos(z)
_SWAP, _LN, _MULT, _EXP, _END, //10 POW a^b=exp(b*ln(a))
_1, _SWAP, _E, _END, //11 POW10
_LN, _1, _0, _LN, _DIV, _END, //12 LOG log(z)=ln(z)/ln(10)
_DUP, _DUP, _DUP, _MULT, _NEG, _1, _ADD, _SQRT, //13 ASIN: asin(z) = -i*ln(i*z+sqrt(1-z*z))
_SWAP, _0, _DUP, _1, _CMPLX, _MULT, _ADD, _LN, _0, _DUP, _1, _CMPLX, _NEG, _MULT,
_SWAP, _ISREAL, _1, _EQ, _IF, _DROP, _1, _8, _0, _MULT, _PI, _DIV, // *RAD - if input was real
_ISREAL, _1, _EQ, _IF, _ELSE, _CMPLX, _DROP, _THEN, // if result is imaginary - set im to 0
_ELSE, _DROP, _THEN, _END,
_DUP, _ASIN, _NEG, //14 ACOS acos(z)=PI/2-asin(z)
_SWAP, _ISREAL, _1, _EQ, _IF, _DROP, _9, _0, _ADD, _ELSE, // +90 - if input was real
_DROP, _PI, _2, _DIV, _ADD, _THEN, _END, // +PI/2 - if input was complex
_DUP, _DUP, _MULT, _1, _ADD, _SQRT, _INV, _MULT, _ASIN, _END, //15 ATAN: atan(z)=asin(z/(sqrt(1+z*z)))
_EXP, _DUP, _INV, _NEG, _ADD, _2, _DIV, _END, //16 SINH sinh(z)=(exp(z)-exp(-z))/2
_EXP, _DUP, _INV, _ADD, _2, _DIV, _END, //17 COSH cosh(z)=(exp(z)+exp(-z))/2
_DUP, _SINH, _SWAP, _COSH, _DIV, _END, //18 TANH tanh(z)=sinh(z)/cosh(z)
_DUP, _DUP, _MULT, _1, _ADD, _SQRT, _ADD, _LN, _END, //19 ASINH asinh(x)=ln(x+sqrt(x*x+1))
_DUP, _DUP, _MULT, _1, _SUB, _SQRT, _ADD, _LN, _END, //20 ACOSH acosh(z)=ln(z+sqrt(z*z-1))
_DUP, _1, _ADD, _SWAP, _NEG, _1, _ADD, _DIV, _SQRT, _LN, _END, //21 ATANH atanh(z)=ln(sqrt((1+z)/(1-z)))
_1, _ADD, _DUP, _DUP, _DUP, _DUP, _1, _2, _MULT, //22 GAMMALN: ln!=(ln(2*PI)-ln(z))/2+z*(ln(z+1/(12*z-1/10/z))-1)
_SWAP, _1, _0, _MULT, _INV, _SUB, _INV, _ADD, _LN, _1, _SUB, _MULT,
_SWAP, _LN, _NEG, _2, _PI, _MULT, _LN, _ADD, _2, _DIV, _ADD, _END,
_DOT, _0, _0, _0, _0, _0, _1, _ADD,//23 HMS2H - round up to prevent leaps
_DUP, _DUP, _INT, _SWAP, _OVER, _SUB, _1, _0, _0, _MULT, _INT, // hh mm
_ROT, _3, _PICK, _SUB, _1, _0, _0, _MULT, _OVER, _SUB, _1, _0, _0, _MULT, // ss
_3, _6, _0, _0, _DIV, _SWAP, _6, _0, _DIV, _ADD, _ADD, _END,// ->s ->h
_DUP, _3, _6, _0, _0, _MULT, _DUP, _ROT, _INT, //24 H2HMS - h->s
_SWAP, _OVER, _3, _6, _0, _0, _MULT, _SUB, _6, _0, _DIV, _INT, // hh mm
_ROT, _OVER, _6, _0, _MULT, _SUB, _3, _PICK, _3, _6, _0, _0, _MULT, _SUB, // ss
_1, _0, _0, _0, _0, _DIV, _SWAP, _1, _0, _0, _DIV, _ADD, _ADD, _END, // hh.mmss
_OVER, _1, _ADD, _SWAP, _POW, _DUP, _1, _SUB, _SWAP, _DIV, _SWAP, _DIV, _END, //25 PV PV(i,n)=((1+i)^n-1)/(1+i)^n/i
_DUP, _DUP, _DUP, _DUP, _MULT, _MULT, _DOT, _0, _7, _MULT, //26 ND
_SWAP, _1, _DOT, _6, _MULT, _NEG, _ADD, _EXP, _1, _ADD, _INV, _SWAP,
_DUP, _MULT, _NEG, _2, _DIV, _EXP, _2, _PI, _MULT, _SQRT, _INV, _MULT, _END,
_OVER, _2, _DIV, _DUP, _MULT, _SWAP, _SUB, _SQRT, _SWAP, _2, _DIV, _NEG, _SWAP, //27 QE x12=-p/2+-sqrt(p*p/4-q)
_OVER, _OVER, _SUB, _ROT, _ROT, _ADD, _END,
_DUP, _ADDDUR, _DROP, //28 CLOCK - Reset duration
_BEGIN, _HMS2H, _3, _6, _0, _0, _0, _0, _0, _MULT, _ADDDUR, // hms to ms and add duration
_1, _SUB, // Time correction (in ms)
_3, _6, _0, _0, _0, _0, _0, _DIV, _H2HMS, // Convert ms to hms
_DUP, _1, _0, _0, _0, _0, _MULT, _INT, _1, _0, _0, _DIV, // Display hm.s
//_DUP, _1, _0, _0, _0, _0, _MULT, _INT, _1, _0, _0, _0, _0, _DIV, // Display h.ms
//_DUP, _1, _0, _0, _MULT, _INT, _1, _0, _0, _DIV, // Display h.m
//_DUP, _1, _0, _0, _MULT, _INT, // Display hm.
_2, _PAUSE, _DROP, _0, _UNTIL, _END, // Print and delete display copies
_0, _DUP, _DUP, _DUP, _DUP, _DUP, //29 CLRSUM
_5, _STO, _6, _STO, _7, _STO, _8, _STO, _9, _STO, _END,
_7, _RCL, _1, _ADD, _7, _STO, //30 SUM+ - n
_DUP, _8, _RCL, _ADD, _8, _STO, // X
_DUP, _DUP, _MULT, _5, _RCL, _ADD, _5, _STO, // XX
_OVER, _MULT, _6, _RCL, _ADD, _6, _STO, // XY
_9, _RCL, _ADD, _9, _STO, _7, _RCL, _END, // Y push(n)
_7, _RCL, _1, _SUB, _7, _STO, //30 SUM- - n
_DUP, _8, _RCL, _SWAP, _SUB, _8, _STO, // X
_DUP, _DUP, _MULT, _5, _RCL, _SWAP, _SUB, _5, _STO, // XX
_OVER, _MULT, _6, _RCL, _SWAP, _SUB, _6, _STO, // XY
_9, _RCL, _SWAP, _SUB, _9, _STO, _7, _RCL, _END, // Y
_8, _RCL, _7, _RCL, _DIV, //32 STAT - mean (X/n)
_DUP, _DUP, _MULT, _7, _RCL, _MULT, _NEG, _5, _RCL, _ADD, // stddev (XX-n*m^2)/(n-1)
_7, _RCL, _1, _SUB, _DIV, _SQRT, _SWAP, _END,
_6, _RCL, _7, _RCL, _MULT, _8, _RCL, _9, _RCL, _MULT, _SUB, //33 L.R. - a
_5, _RCL, _7, _RCL, _MULT, _8, _RCL, _DUP, _MULT, _SUB, _DIV,
_DUP, _8, _RCL, _MULT, _NEG, _9, _RCL, _ADD, _7, _RCL, _DIV, _SWAP, _END, // b
_OVER, _DIV, _1, _0, _0, _MULT, _END, //34 % x/B*100%
_OVER, _SUB, _OVER, _DIV, _1, _0, _0, _MULT, _END, //35 DELTA% (x-B)/B*100%
_DUP, _INT, _SUB, _END, //36 FRAC
_DUP, _PI, _MULT, _1, _8, _0, _DIV, //37 DEG<>RAD
_SWAP, _1, _8, _0, _MULT, _PI, _DIV, _END,
_DUP, _1, _DOT, _8, _MULT, _3, _2, _ADD, //38 C<>F
_SWAP, _3, _2, _SUB, _1, _DOT, _8, _DIV, _END,
_DUP, _1, _DOT, _6, _0, _9, _3, _4, _4, _DUP, _DUP, //39 KM<>MI
_ROT, _SWAP, _DIV, _ROT, _ROT, _MULT, _END,
_DUP, _3, _DOT, _3, _7, _0, _0, _7, _9, _DUP, _DUP, //40 M<>FT
_ROT, _MULT, _ROT, _ROT, _DIV, _END,
_DUP, _2, _DOT, _5, _4, _DUP, _DUP, _ROT, _SWAP, _DIV, _ROT, _ROT, _MULT, _END, //41 CM<>IN
_DUP, _2, _DOT, _2, _0, _4, _6, _2, _3, _DUP, _DUP, //42 KG<>LBS
//_ROT, _SWAP, _DIV, _ROT, _ROT, _MULT, _END,
_ROT, _MULT, _ROT, _ROT, _DIV, _END,
_DUP, _3, _DOT, _7, _8, _5, _4, _1, _2, _DUP, _DUP, //43 L<>GAL
_ROT, _SWAP, _DIV, _ROT, _ROT, _MULT, _END,
};
// Command code defines
#define _0 0 // Intrinsic commands
#define _1 1
#define _2 2
#define _3 3
#define _4 4
#define _5 5
#define _6 6
#define _7 7
#define _8 8
#define _9 9
#define ALMOSTZERO 1e-37 // Limits to decide if sci or fix
#define OVERFLOW 36 // Max power of 10 before overflow
#define OVERFLOWEXP 87 // Max power of e before overflow
#define FIXMIN 1e-3 // Limits for fix display guarantee maximal
#define FIXMAX 1e7 // number of significant digits
#define FIXSCI 3 // Display 3 decimals in scientific view
//#define FIXMANT 3 // FIX in 10th-exponent
#define ISF 1 // F-key demanded
#define ISG 2 // G-key demanded
#define RAD ((180.0)/(PI)) // 180/PI
#define VIEWMAX 5
#define VIEWRE 1 // Number view mode (0=re 1=im 2=abs 3=angle)
#define VIEWIM 2
#define VIEWABS 3
#define VIEWANGLE 4 // Time in ms to display next animation step
#define PRGNAMEMAX 2 // Maximal number of characters of program name
#define PRGSIZEMAX 128 // Max size of prg, prgptr, prgbuf
#define FLONGPRESSTIME 350 // Time in ms when f longpress starts
#define DELTAX 1E-4 // Delta for solver
#define INTSTRIPES 10 // Number of Simpson stripes for integrating
// EEPROM addresses
#define EEDARKTIME 1 // EEPROM address for display off time
#define EEBASE 2 // Store base
#define MEMNR 10 // Maximal number of constant memories in EEPROM (slots)
#define EEMEM 3 // Starting EE-address for constants (2xMEMNRx4)
#define EEMEMB 83 // Starting EE-address for base number (8)
#define MENUITEMS 32 // Number of selectable user menu items
#define EEMENU 91 // Start of user menu in EEPROM (MENUITEMS bytes)
#define EEUSTART 123 // EEPROM address of user programs
#define EEUEND EEPROM.length()
#define EEU (EEUEND-EEUSTART) // Available user memory
// GLOBAL VARIABLES
static byte dbuf[DIGITS]; // Display buffer
static byte brightness = 0; // Brightness
struct data { // Structure for numbers
double r, i; // Real, imaginary
int64_t b; // Integer, base
};
#define C0 (struct data){NULL, NULL,NULL} // Complex NULL
#define DATASTACKSIZE 26 // DATA STACK
struct data ds[DATASTACKSIZE];
static byte dp = 0;
#define ADDRSTACKSIZE 64 // ADDRESS STACK
static int as[ADDRSTACKSIZE];
static byte ap = 0;
byte cl = 0; // CONDITIONAL LEVEL
static int mp; // MEMPOINTER (builtin and user functions)
static int breakmp; // Holds memory pointer while break
static byte decimals = 0; // Number of decimals entered (input after decimal dot)
static boolean isdot = false; // True if dot was pressed and decimals will be entered
static byte dotpos = DIGITS; // Position of dot for printing (dbuf)
static boolean isnewnumber = true; // True if stack has to be lifted before entering a new number
static boolean isprintscreen = true; // True, if screen should be printed
static byte key = END; // Holds entered key
static byte oldkey = END; // Holds oldkey - to prevent keyrepeat
static byte fgm = 0, setfgm = 0; // F-key variables
static boolean isfloated = false; // True, if data stack was floated
static byte select; // Selected options
static boolean isdict = false; // True for dict browsing
static boolean ismenu = false; // True, if menu was demanded
static boolean issetusr = false; // True if dict is used for setting usr menu
static byte setusrselect; // Stores selected cmd value to store
static boolean ismenusetusr; // True for choosing user menu place
static boolean ispolar = false; // Shows imaginary number in polar format (else rectangular)
static byte view = 0; // Number view (1=re 2=im 3=abs 4=angle)
static boolean isprgdict = false, isprgmenu = false, isprgnew = false;
static byte prgbuflen; // Size of program in program buffer
static byte prgeditstart = 0;
static byte prgbuf[PRGSIZEMAX], oldprgbuflen; // Program buffer for fast editing
static boolean isprgeditfirst = false;
static boolean isprgedit = false; // True, if program is editet
static byte prgselect = 0; // Number of selected program
static boolean isprgselect = false; // Used for selecting program
static int prgaddr; // EEPROM address of actual program
static boolean isprgrename = false; // True if program should be renamed
static byte renamenr = 0; // Stores selected prg value to rename
static byte pause = 0; // Pause time in n * 250 ms
static long timestamp; // Timestamp for f longpress
static long durationtimestamp = millis(); // Timestamp for add-duration-function
static boolean freleased = false; // Used for releasing longpressed f-key
static long powertimestamp = 0; // Needed for timing of power manangement
static byte darktime; // Time of inactivity for dark screen (in 10 x s)
static boolean darkscreen = false; // Shows empty dbuf, if true
static int sou; // Size of user programs
static byte nou; // Number of user programs
static byte base = 0; // BASE
static boolean isAF; //Next keypress is hexA ... hexF
boolean isgetkey = false; // Needed for getkey function
static char alpha[DIGITS] = {NULL}; // String buffer (alpha) for user text output
static boolean isprintalpha = false; // Print alpha if true
static byte cycles; // Solver cycles
static double x0, x1, f0; // Old and new solve-value
static boolean issolve = false, isint = false; // True if solving or integrating is demanded
static double inta, intb, intdelta, intx, intf; // INT variables
static byte anipos = 1; // Position of animated bit (0 ... no animation)
static byte anicount = _END; // Number of animations (_END ... infinite animation)
#define _AEXIT 2 // Number of animations when exiting any mode
#define _MA 0 // Matrix A
#define _MB 1 // Matrix B
#define _MC 2 // Matrix C
static double m[6][3][3]; // Matrices A:0/1 B:2/3 C:4/5
boolean ismat = false, ismatview = false; // Matrix and view mode
static byte mselect = 0; // Selected matrix (A or B)
static double mdet, mdeti; // Determinant of matrix
byte matr = 0, matc = 0; // Row and col of selected matrix slot
// FUNCTION POINTER ARRAY
static void _nop(void) {} // NOP - no operation
static void _n0(void) { // 0
_numinput(_0);
}
static void _n1(void) { // 1
_numinput(_1);
}
static void _n2(void) { // 2
_numinput(_2);
}
static void _n3(void) { // 3
_numinput(_3);
}
static void _n4(void) { // 4
_numinput(_4);
}
static void _n5(void) { // 5
_numinput(_5);
}
static void _n6(void) { // 6
_numinput(_6);
}
static void _n7(void) { // 7
_numinput(_7);
}
static void _n8(void) { // 8
_numinput(_8);
}
static void _n9(void) { // 9
_numinput(_9);
}
static void _absolute(void) { // ABS
seekmem(_ABS);
}
static void _acos(void) { // ACOS
seekmem(_ACOS);
}
static void _acosh(void) { // ACOSH
seekmem(_ACOSH);
}
static void _add(void) { // ADD + (a+i*b)(c+i*d)=(a+c)+i*(b+d)
struct data b = dpop(), a = dpop();
dpush({a.r + b.r, a.i + b.i, a.b + b.b});
}
static void _addduration(void) { // ADD DURATION
dpushr(dpopr() + (millis() - durationtimestamp));
durationtimestamp = millis();
}
static void _asin(void) { // ASIN
seekmem(_ASIN);
}
static void _asinh(void) { // ASINH
seekmem(_ASINH);
}
static void _atan(void) { // ATAN
seekmem(_ATAN);
}
static void _atanh(void) { // ATANH
seekmem(_ATANH);
}
static void _base(void) { // BASE MODE
if (base) { // Return from base mode
B2stack(); base = 0;
anicount = _AEXIT;
}
else { // Switch to base mode
base = dpopr();
if (base > 1) stack2B(); else base = 0;
}
EEPROM[EEBASE] = base;
}
static void _batt(void) { // BATT
dpushr((double)(1126400L / rawadc()) / 1000.0);
}
static void _begin(void) { // BEGIN
apush(mp);
}
static void _break(void) { // BREAK
breakmp = mp; mp = 0;
isprintscreen = true;
}
static void _ce(void) { // CE
if (isdot) {
if (decimals)
dpushr(((long)(dpopr() * pow10(--decimals)) / pow10(decimals)));
else isdot = false;
}
else {
if (base) {
int64_t a = dpopb();
a = a / base;
if (!a) isnewnumber = true;
else dpushb(a);
}
else {
long a = dpopr() / 10.0;
if (!a) isnewnumber = true;
else dpushr(a);
}
}
}
static void _clock(void) { // CLOCK
seekmem(_CLOCK);
}
static void _clr(void) { // CLR
dp = 0;
_textclear();
}
static void _comb(void) { // COMB nCr=n!/r!/(n-r)!=nPr/r!
byte k = dpushr(dpopr());
_perm();
for (byte i = 1; i <= k; i++) dpushr(dpopr() / i);
}
static void _complex(void) { // COMPLEX
if (!base) {
if (isreal()) { // # Stack -> complex
if (ispolar) { // Polar
double b = dpopr(), a = dpopr();
dpush({a * cos(b / RAD), a * sin(b / RAD), 0LL});
}
else { // Rectangular
double b = dpopr();
dpush({dpopr(), b, 0LL});
}
}
else { // # Complex -> stack
if (ispolar) { // Polar
struct data a = dpop();
dpushr(absolute(a.r, a.i)); dpushr(angle(a.r, a.i));
}
else { // Rectangular
struct data a = dpop();
dpushr(a.r); dpushr(a.i);
}
}
}
}
static void _condelse(void) { // CONDITION ELSE
if (!cl) msgnr = MSGERROR; // ELSE without corresponding IF
else {
_condseek(); // Seek next THEN