-
Notifications
You must be signed in to change notification settings - Fork 0
/
0-Tachyon V3.0 JUNO.spin
7325 lines (6105 loc) · 661 KB
/
0-Tachyon V3.0 JUNO.spin
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
' NOTE: V3 requires BST (or PropellerIDE) to compile due to the >1024 DAT symbols
DAT { *** CHANGELOG *** }
version long 300_160819
vertime word 2230
vername byte "3.0 JUNO" ' fixed 8 character version name
' serial console parameters
baudrate long baud ' The baudrate is now stored as a variable
byte rxd,txd,0,0 ' default pins for console
org $10
s ' just an offset to be used in DAT sections rather than the distracting +$10
CON { *** CLOCK MODES *** }
{
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000 ' <--- AUTOMATIC 5 or 10MHz operation change at boot
sysfreq = 80_000_000
'}
' { 6MHZ CRYSTAL
_clkmode = xtal1 + pll16x
_xinfreq = 6_000_000
sysfreq = 96_000_000
'}
baud = 115200 ' <-- user change - tested from 300 baud to 3M baud
{{
.:.:-- TACHYON --:.:.
A very fast and very small Forth byte code interpreter for the Propeller chip.
2012..2016 Peter Jakacki
STARTUP SCREEN
VER: Propeller .:.:--TACHYON--:.:. Forth V3.0 JUNO 300160720.0000
FREQ: 80MHZ (PLLEN OSCEN XTAL1 PLL8X )
NAMES: $5871...74C6 for 7,253 bytes (+741)
CODE: $0930...3D70 for 13,376 bytes (+2,307)
RAM: 6,913 bytes free
BUILD: FIRMWARE BUILD DATE 000000:000000 BOOTS: 4 runtime 329,069
BOOT: EXTEND.bootPOLL: DEMO0
MODULES LOADED:
346D: VGA.fth VGA text driver 150709-2200
1787: EXTEND.fth Primary extensions to TACHYON kernel - 160720-1500
ROMS
0848 VGA32x15
0236 HSSERIAL
1648 SIDEMU
1940 QUADUART
0196 MONO16
1900 F32 POLL: DEMO0
----------------------------------------------------------------
FEATURES
V2
Stacked backward branch references - fast and simple looping
Fast load features
Large receive buffer
Top 4 stack parameters are accessed as fixed registers - overflow into hub RAM
Small memory footprint
Low level words and run-time bytecode interpreter in PASM
Byte codes are read from hub RAM and directly address first 256 longs of PASM code in cog
User PASM mode via stacks
Interpreted bytecode definitions are referenced as:
2 bytes - vectored CALL opcode + byte index into 512 entry table
All literals and strings are byte aligned
Fast access Forth registers avoids deep stacks and juggling
Fast I/O bit-bashing support for clocked and asynchronous data (2.8MHz clock speed)
Flexible SPI or I2C PASM code support words in kernel
Construct fast serial drivers with minimal code
VM Kernel compiled in standard manner via Spin tools so other Spin objects can be combined
Four stacks in COG RAM: Data, Return, Loop, and Loop Branch
Access loop indices outside of definitions allows efficient factoring
Avoids manipulation and corruption of return stack
Static stack arrays for direct addressing of stack items
Intrinsically safe data stack overflow and underflow - optional error reporting
400ns minimum instruction cycle time (single bytecode, hub access average)
Empty loops can execute in 550ns to 875ns (absolute worst case)
Two to one stack operations ( + * AND etc) inc opcode fetch take 900ns to 1.087us (absolute worse case) *
Flexible number input using common symbols for prefixes and suffixes as well as allowing intermixed symbols
V2.4
Adds KEY! (KEY)
Modifies console KEY now returns with null if there was no key - KEY?
----------------MEMORY MAP---------------
160718
256 entry XCALL saves >400 bytes over 512 entries for larger apps
Kernel used 165 entries
-----------------------------------------------------------------------------------------------
vecsize = 256
39A3: EASYFILE.fth FAT32 Virtual Memory Access File System Layer V1.1 150213-1530
337C: SDCARD.fth SD CARD Toolkit - 150827.0000
330B: P1656.fth P1656 HARDWARE DEFINITIONS 160325.0000
1787: EXTEND.fth Primary extensions to TACHYON kernel - 160627-1200
NAMES: $4F2B...70EC for 8,641 bytes (+1,377)
CODE: $0924...481E for 16,122 bytes (+3,707)
CALLS: 0 vectors free
RAM: 1,805 bytes free
-----------------------------------------------------------------------------------------------
vecsize = 512
3CB0: EASYFILE.fth FAT32 Virtual Memory Access File System Layer V1.1 150213-1530
3724: SDCARD.fth SD CARD Toolkit - 150827.0000
36B8: P1656.fth P1656 HARDWARE DEFINITIONS 160325.0000
1BC7: EXTEND.fth Primary extensions to TACHYON kernel - 160627-1200
NAMES: $4F3E...70E9 for 8,619 bytes (+1,377)
CODE: $0924...49E0 for 16,572 bytes (+3,376)
CALLS: 185 vectors free
RAM: 1,374 bytes free
HERE .WORD 49E0 ok
@NAMES .WORD 4F3E ok
-----------------------------------------------------------------------------------------------
vecsize = 256 and tigher memory + ROMs
MODULES LOADED:
39BB: EASYFILE.fth FAT32 Virtual Memory Access File System Layer V1.1 150213-1530
3394: SDCARD.fth SD CARD Toolkit - 150827.0000
3323: P1656.fth P1656 HARDWARE DEFINITIONS 160325.0000
1787: EXTEND.fth Primary extensions to TACHYON kernel - 160627-1200
NAMES: $52EE...74B0 for 8,642 bytes (+1,377)
CODE: $0930...4836 for 16,134 bytes (+3,707)
CALLS: 0 vectors free
RAM: 2,744 bytes free
-----------------------------------------------------------------------------------------------
}}
'-------------------- WHAT'S NEW --------------------'
{HELP CHANGELOG
V3
160804 Added kernel version of WORDS. EMIT now has translation table for first 16 control codes such as LF suppression
160803 Fixed sneaky bug in ping-pong networking - rxdat needed to be initialized to zero but was compiled as a "res"
160719 Added ROMs into free space that later is overwritten by metacompile words but SAVEROMS moves these to upper EEPROM
V3 is defined and leaves TRUE on the stack
V2.10 Memory map optimizations
100718 Reducing reserved XCALL table to 256 longs and removing extra call methods - but allowing for easy resize anyway
Removed VCALL and ZCALL
Renamed NFA>CFA to NFA>BFA (byte field address) and >PFA to >CFA (pointer to the code itself)
V2.9
100717 Added standard escape sequences for strings such as \<anything> \$xx \t \n \r
160613 Fixed buffer areas as constants
160612 Improved ping-pong timing
160606 Updated to include functions to configure the unit
160602 Integrating new ping-pong RS485 networking driver - provides full-duplex console operation
V2.8
160524 New [SERIN] module for fast serial receive - mask and baud rate preset with [SERIN]
160514 Added an emit register to hold the last character sent (for now) to facilitate a virtual console
160509 Aligned rx image to 128 byte boundary to allow for 128 byte EEPROM page sizes
Also dropped rxrd and rxwr to just before boundary to allow a full 512 bytes of buffer before kernel image
This little change means faster error-free load times due to extra buffering
160508 Removed MYOP - redundant
Added 8<< and 8>> for fast multi-bit shifts including hybrids such as 16<< 16>> 9<< 9>> (avoids stack push and pop)
160507 Fixed &00.xx.xx.xx bug
160415 Change NIP to SWAP DROP - this is only about 200ns slower than dedicated NIP due to hub access synch
Added SPICE instruction to disable the SPI chip-enable using the COGREG mask
V2.7
150902 Add [CAP] module to perform fast I/O capture to buffers. Disable ONEWAVE
150826 Added 9BITS opcode to perform a fast $1FF AND as used in virtual memory addressing. Only needed one long inserted into >B code
150712 Rearranged task registers etc to avoid having to duplicate more than necessary for a new task.
150621 Added VGA text support
V2.6
150608 Arrange serial receive routine to use larger 2K BUFFERS during TACHYON source code load for faster loading line delays of <5ms
V2.5
150226 Add carry operation - saves carry from +- in lsb of X, fetch with "c" word
150522 Removed buggy SPIOD and replaced with MCP32 module for MCP3208 chips etc.
150521 Replaced UM/MOD2 with UM/MOD32 and UM/MOD64 and set as single byte opcodes.
Added SQRT RUNMOD and also made RUNMOD a single-byte opcode (fraction faster)
150520 Modified UM/MOD2 to accept a bit count for justified dividend to permit faster 32-bit ops
-1500 Modified # number print words to accept a 64-bit number but high long is held in cntr REG to
ensure compatibility with other defintions built on # words. prefix print with <D>
150520 Added UM/MOD2 and */ and changed U/MOD and U/ to bytecode defs
Improved 2+ and 2- by using INC INC etc
Change default base to decimal
V2.4
150126 Increased depth of return stack from 22 to 26, decreased branch stack from 6 to 5 (tested depths)
150112 Fix CALL16 for immediate words - added method to extract address and call
150105 Added CALL16 methods to CREATESTR and BCOMPILE
Improved speed and method of +CALL from 5.4ms to 2ms (fixed bug which allowed table overflow)
141209 FIxed MYOP to use variable buffer base
141103 Made structure mismatch call ERROR which also emits a string of ?s
141030 Added WS2812CL to perform 24-bit color table lookup from 8-bit color per RGB LED pixel
1410xx
140724 Modified +FIB to become BOUNDS instead
140722 Automatically convert case of failed search word to upper case and try again
140721 Fixed COMMENT words so that the terminator is passed through (no more empty comments needing two CRs)
Reshuffled opcodes between first and second page
Removing KEY? in favour of a standard KEY operation which returns with a false on no key or a key with msb set
If a word fails to be found in the dictionary and it starts with a lower-case character then convert it to uppercase and try again
140717 Adding in MYOP and removing CMPSTR so that it only loads as a RUNMOD during compling blocks of source, otherwise runs in HL bytecode.
Working towards integrating runtime OBEX
V2.3
140717 Renamed CROP to MYOP to allow for user programmable opcode - not ever used in kernel or EXTEND
Optimising STREND and CMPSTR
Decided this should be V2.4 as CMPSTR is to removed from cog kernel and only loaded as a RUNMOD during TACHYON .... END loads
Refer to V2.3 for older changelogs
}
CON
rxsize = 256 ' Serial rx buffer - reuses serial receive cog code image – can extend into BUFFERS area
vecsize = 256 ' number of words reserved for XCALL table
vecshr = >|(vecsize*4)-1
extstk = $7F80 ' locate external data stack at end (overflows but it's ROM)
' MULTI-DROP
_myadr = $81 ' default node address
_gbl = $EF ' address all nodes - no response
_BUFFERS = $7700 ' reclaimed 2k area used for SD, ROM, and general buffers
registers = $0030
CON { *** PORT ASSIGNMENTS *** }
' Standard Port assignments
scl = 28
sda = 29
txd = 30
rxd = 31
' Stack sizes
datsz = 4 ' expands into hub RAM
retsz = 28
loopsz = 8
branchsz = loopsz/2 ' fast FOR/DO branch address
numpadsz = 26 ' We really only need a large buffer for when long binary numbers with separators are used – 26 digits for double number 18,446,744,073,709,551,615
wordsz = 39 ' any word up to 37 characters (1 count, 1 terminator)
tasksz = 8 ' 8 bytes/task RUN[2] FLAG[1]
' flags
echo = 1
linenums = 2 ' prepend line number to each new line
ipmode = 4 ' interpret this number in IP format where a "." separates bytes
leadspaces = 4
prset = 8 ' private headers set as default
striplf = $10 ' strip linefeeds from output if set ( not used - LEMIT replaces this !!!)
sign = $20
comp = $40 ' force compilation of the current word - resets each time
defining = $80
DAT { *** TASK REGISTERS *** }
' Allocate storage memory for buffers and other variables
long 0[64] 'Variables used by kernel + general-purpose
' Task registers can be switched easily by setting "regptr" ( 7 COGREG! )
' New tasks may only need room for the first 32 or 72 bytes
org 0
' register offsets within "registers". Access as REG,delim ... REG,base ... etc
'
' Minimum registers required for a new task - other registers after the ' ---- are not needed other than by the console
temp res 12 ' general purpose
cntr res 4 ' hold CNT or temp
' @16
uemit res 2 ' emit vector – 0 = default
ukey res 2 ' key vector
keypoll res 2 ' poll user routines - low priority background task
base res 2 ' current number base + backup location during overrides
baudcnt res 4 ' SERIN SEROUT baud cnt value where baud = clkfreq/baudcnt – each cog can have it's own
uswitch res 4 ' target parameter used in CASE structures
flags res 2 ' echo,linenums,ipmode,leadspaces,prset,striplf,sign,comp,defining
keycol res 1 ' maintains column position of key input
wordcnt res 1 ' length of current word (which is still null terminated)
wordbuf res wordsz ' words from the input stream are assembled here
' numpad may continue to build backwards into wordbuf for special cases such as long binary numnbers
numpad res numpadsz ' Number print format routines assemble digit characters here – builds from end - 18,446,744,073,709,551,615
padwr res 1 ' write index (builds characters down from lsb to msb in MODULO style)
'
' ------ console only registers – not required for other tasks
'
unum res 2 ' User number processing routine - executed if number failed and UNUM <> 0
anumber res 4 ' Assembled number from input
bnumber res 4
digits res 1 ' number of digits in current number that has just been processed
dpl res 1 ' Position of the decimal point if encountered (else zero)
' WORD aligned registers
ufind res 2 ' runs extended dictionary search if set after failing precompiled dictionary search
createvec res 2 ' If set will execute user create routines rather than the kernel's
rxptr res 2 ' Pointer to the terminal receive buffer - read & write index precedes
rxsz res 2 ' normally set to 256 bytes but increased during block load
corenames res 2 ' points to core kernel names for optimizing search sequence
oldnames res 2 ' backup of names used at start of TACHYON load
names res 2 ' start of dictionary (builds down)
prevname res 2 ' temp location used by CREATE
fromhere res 2 ' Used by TACHYON word to backup current “here” to determine code size at end of load
here res 2 ' pointer to compilation area (overwrites VM image)
codes res 2 ' current code compilation pointer (updates "here" or is reset by it)
cold res 2 ' pattern to detect if this is a cold or warm start ($A55A )
autovec res 2 ' user autostart address if non-zero - called from within terminal
errors res 2
linenum res 2
' Unaligned registers
delim res 2 ' the delimiter used in text input and a save location
prompt res 2 ' pointer to code to execute when Forth prompts for a new line
accept res 2 ' pointer to code to execute when Forth accepts a line to interpret (0=ok)
prevch res 2 ' used to detect LF only sequences vs CRLF to perform auto CR
emitreg res 4 ' 160514 addition for virtual console - 160705 using txon flg in emitreg+3
'lastkey res 1 ' written to directly from serialrx
writekey res 1
keychar res 1 ' override for next key character to insert a characer into the stream
spincnt res 1 ' Used by spinner to rotate busy symbol
prefix res 1 ' NUMBER input prefix
suffix res 1 ' NUMBER input suffix
res 3
tasks res tasksz*8 ' (must be long aligned)
endreg res 0
DAT { *** VECTOR TABLE *** }
{ *** BYTECODE DEFINITIONS VECTOR TABLE *** }
{
Kernel bytecode definitions need to be called and this table makes it easy to do so
with just a 2 byte call. Extra memory may be allocated for user definitions as well
The Spin compiler requires longs whereas we only need 16-bit words but this will work anyway.
The runtime compiler can reuse the high-word of all these longs and compile a YCALL rather than
an XCALL so that the high-word is used instead.
Also another table has been added to expand the call vectors up to 1024 entries.
So there are 256 16-bits vectors x 4 pages using
XCALL low word of first 1K page
YCALL high word of first 1K page
ZCALL low word of second 1K page
VCALL High word of second 1K page
Use of a vector table is almost necessary for the Spin compiler just so we can reference bytecode by name without having to align on word boundaries and
add offsets etc. So a call to the an interpreted word such as GETWORD made up of bytecodes is simply
byte XCALL,xGETWORD
without having to worry about alignment or offsets rather than a 16-bit absolute call which would awkwardly look like this:
byte CALL16,(GETWORD+s)>>8,GETWORD+s
}
org 0 ' ensure references can be reduced to a single byte index to be called by XCALL xx
'
XCALLS
' NOTE: this table is limited to 1024 word entries but leave room for extensions and user application to use the rest of these
xXCALLS long @_XCALLS+s
xLSTACK long @LSTACK+s
xSETQ long @SETQ+s
xLT long @LT+s
xZLT long @ZLT+s
xULT long @ULT+s
' xSAR long @_SAR+s
xUDIVIDE long @UDIVIDE+s
xUDIVMOD long @UDIVMOD+s
xMULDIV long @MULDIV+s
xWITHIN long @WITHIN+s
xFILL long @FILL+s
xERASE long @ERASE+s
xms long @ms+s
xCOMMENT long @COMMENT+s
xBRACE long @BRACE+s
xCURLY long @CURLY+s
xIFNDEF long @IFNDEF+s
xIFDEF long @IFDEF+s
xPRTHEX long @PRTHEX+s
xPRTBYTE long @PRTBYTE+s
xPRTWORD long @PRTWORD+s
xPRTLONG long @PRTLONG+s
xPRTSTK long @PRTSTK+s
xPRTSTKS long @PRTSTKS+s
xDEBUG long @DEBUG+s
xDUMP long @DUMP+s
xCOGDUMP long @COGDUMP+s
xREBOOT long @_REBOOT+s
xSTOP long @STOP+s
xLOADMOD long @aLOADMOD+s
xTX485 long @lTX485+s
xSERIN long @lSERIN+s
xSSD long @SSD+s
xESPIO long @ESPIO+s
xBSPIWR long @BSPIWR+s
xSPIO long @SPIO+s
xMCP32 long @MCP32+s
xSDRD long @SDRD+s
xSDWR long @SDWR+s
xPWM32 long @PWM32+s
xPWMST32 long @PWMST32+s
xPLOT long @PLOT+s
xPLAYER long @PLAYER+s
'xONEWAVE long @ONEWAVE+s
xBCA long @_BCA+s
xWS2812 long @_WS2812+s
'xWS2812CL long @_WS2812CL+s
xSQRT long @_SQRT+s
xCAP long @_CAP+s
xRCMOVE long @RCMOVE+s
xCLS long @CLS+s
xEMIT long @EMIT+s
xSPACE long @SPACE+s
xBELL long @BELL+s
xCR long @CR+s
xOK long @OK+s
xSPINNER long @SPINNER+s
xBIN long @BIN+s
xDECIMAL long @DECIMAL+s
xHEX long @HEX+s
xREADBUF long @READBUF+s
xCONKEY long @CONKEY+s
xKEY long @KEY+s
xWKEY long @WKEY+s
xSEQKEY long @SEQKEY+s
xECHOKEY long @ECHOKEY+s
xLASTKEY long @_LASTKEY+s
xQEMIT long @QEMIT+s
xTOUPPER long @TOUPPER+s
xPUTCHAR long @PUTCHAR+s
xPUTCHARPL long @PUTCHARPL+s
xSCRUB long @SCRUB+s
xdoCHAR long @doCHAR+s
xGETWORD long @GETWORD+s
xTICK long @TICK+s
xATICK long @ATICK+s
xNFATICK long @NFATICK+s
x_NFATICK long @_NFATICK+s
xTOVEC long @TOVEC+s
xBFACFA long @BFACFA+s
xIFEXIT long @IFEXIT+s
xSEARCH long @SEARCH+s
xFINDSTR long @FINDSTR+s
xEXECUTE long @EXECUTE+s
xGETVER long @GETVER+s
xPRTVER long @PRTVER+s
xTODIGIT long @TODIGIT+s
xNUMBER long @NUMBER+s
xTERMINAL long @TERMINAL+s
xCONSOLE long @CONSOLE+s
xRXPARS long @RXPARS+s
'xVGA long @VGA+s
x_NUMBER long @_NUMBER+s
xGRAB long @GRAB+s
xRESFWD long @RESFWD+s
xATPAD long @ATPAD+s
xHOLD long @HOLD+s
xTOCHAR long @TOCHAR+s
xRHASH long @RHASH+s
xLHASH long @LHASH+s
xHASH long @HASH+s
xHASHS long @HASHS+s
xDNUM long @DNUM+s
x_STR long @_STR+s
xPSTR long @PSTR+s
xPRTSTR long @PRTSTR+s
xSTRLEN long @STRLEN+s
xUPRT long @UPRT+s
xPRT long @PRT+s
xPRTDEC long @PRTDEC+s
xLITCOMP long @LITCOMP+s
xBCOMP long @BCOMP+s
xBCOMPILE long @BCOMPILE+s
xCCOMP long @CCOMP+s
xWCOMP long @WCOMP+s
xLCOMP long @LCOMP+s
xSTACKS long @STACKS+s
x_STR_ long @_STR_+s
x_PSTR_ long @_PSTR_+s
x_IF_ long @_IF_+s
x_ELSE_ long @_ELSE_+s
x_THEN_ long @_THEN_+s
x_BEGIN_ long @_BEGIN_+s
x_UNTIL_ long @_UNTIL_+s
x_AGAIN_ long @_AGAIN_+s
x_REPEAT_ long @_REPEAT_+s
xMARK long @MARK+s
xUNMARK long @UNMARK+s
xVECTORS long @VECTORS+s
xTASK long @TASK+s
xIDLE long @IDLE+s
xALLOT long @ALLOT+s
xALLOCATED long @ALLOCATED+s
xATO long @Ato+s
xATATR long @ATATR+s
xCOLON long @COLON+s
x_COLON long @_COLON+s
xPUBCOLON long @PUBCOLON+s
xPRIVATE long @PRIVATE+s
xUNSMUDGE long @UNSMUDGE+s
xENDCOLON long @ENDCOLON+s
xCOMPILES long @COMPILES+s
xCREATE long @CREATE+s
xCREATEWORD long @CREATEWORD+s
xCREATESTR long @CREATESTR+s
xAddACALL long @AddACALL+s
xHERE long @_HERE+s
xNFABFA long @NFABFA+s
x_TACHYON long @_TACHYON+s
xERROR long @ERROR+s
xNOTFOUND long @NOTFOUND+s
xDISCARD long @DISCARD+s
'xAUTORUN long @AUTORUN+s
xFREE long @FREE+s
'xAUTOST long @AUTOST+s
xFIXDICT long @FIXDICT+s
xBUFFERS long @BUFFERS+s
xCOLDST long @COLDST+s
xSWITCH long @_SWITCH+s
xSWITCHFETCH long @SWITCHFETCH+s
xISEQ long @ISEQ+s
xIS long @IS+s
xISEND long @ISEND+s
xISWITHIN long @ISWITHIN+s
xInitStack long @InitStack+s
xSPSTORE long @SPSTORE+s
xDEPTH long @_DEPTH+s
xCOGINIT long @aCOGINIT+s
xSET long @SET+s
xCLR long @CLR+s
xWORDS long @WORDS+s
' Reserve the rest of the area possible
xLAST long 0[vecsize-xLAST]
' plus one extra for termination
xEND long -1
CON
loadsz = 21 ' Specifies the number of longs to load with LOADMOD for a RUNMOD module
DAT { *** RUNMODs *** }
{ TACHYON VM CODE MODULES }
' There are a number of longs reserved in the cog for a code module which can be loaded with LOADMOD and executed with RUNMOD
org $01F0-loadsz ' fixed address - high-level code can always assume RUNMOD' cog origin is here
pRUNMOD
_RUNMOD res loadsz
org _RUNMOD
rTX485
or outa,rtepin ' enable transmitter
or dira,rtepin
or dira,rtrpin ' make tr a transmit outout (along with te)
add tos,#$100 wc ' add a stop bit (carry = start bit)
mov R0,cnt
add R0,tick485
:txl muxc outa,rtrpin ' output bit
shr tos,#1 wz,wc ' lsb first
waitcnt R0,tick485 ' bit timing
if_nz_or_c jmp #:txl ' next bit (stop bit: z & c)
andn dira,rtrpin ' Turn data line back to receive
' waitcnt R0,tick485
andn outa,rtepin ' Turn chip back to receive (force high for deglitch)
jmp #DROP
rtrpin long 0
rtepin long 0
tick485 long 0
lTX485 '( trmask temask ticks -- )
byte _WORD,(@rTX485+s)>>8,@rTX485+s
byte XCALL,xLOADMOD
byte _WORD,tick485>>8,tick485,XOP,pCOGSTORE
byte _WORD,rtepin>>8,rtepin,XOP,pCOGSTORE
byte _WORD,rtrpin>>8,rtrpin,XOP,pCOGSTORE
byte EXIT
org _RUNMOD
rSERIN ' ( -- dat )
mov R2,#9
serlp mov X,rticks
shr X,#1 ' half bit time
waitpne rmask,rmask ' wait for a low = start bit
add X,cnt ' uses special start bit timing
waitcnt X,rticks
test rmask,ina wz ' sample middle of start bit
if_nz jmp #serlp ' restart if false start otherwise bit time from center
serdat waitcnt X,rticks ' wait until middle of first data bit
test rmask,ina wc ' sample bit 0
rcl ACC,#1
djnz R2,#serdat
if_nc jmp #rSERIN ' framing error
rev ACC,#23
and ACC,#$FF
jmp #PUSHACC
rmask long 0
rticks long 0
lSERIN '( ticks mask -- )
byte _WORD,(@rSERIN+s)>>8,@rSERIN+s
byte XCALL,xLOADMOD
byte _WORD,rmask>>8,rmask,XOP,pCOGSTORE
byte _WORD,rticks>>8,rticks,XOP,pCOGSTORE
byte EXIT
{
org _RUNMOD
' Write byte to I2C bus
' COGREGS: 0=scl 1=sda
' I2CWR ( send -- ack ) ( A: miso mosi sck )
_I2CWR mov R1,#8
i2cwrlp andn OUTA,sck ' clock low
or DIRA,mosi ' make sure data is an output
shl sdat,#1 wc ' msb first
muxc OUTA,mosi ' send next bit of data out
call #i2cdly
or OUTA,sck ' clock high
djnz R1,#i2cwrlp
andn OUTA,sck ' get ready to read ack
andn DIRA,mosi ' float SDA
or OUT,sck
jmp unext
ic2dly nop
i2cdly_ret ret
I2CWR byte _WORD,(@_I2CWR+s)>>8,@_I2CWR+s
byte XCALL,xLOADMOD,EXIT
}
org _RUNMOD
' BLOCK WRITE SPI
' BSPIWR ( src cnt -- )
_BSPIWR
andn OUTA,spice ' chip select low
BBlp rdbyte X,tos+1
add tos+1,#1 ' inc addr
mov R1,#8
shl X,#24 ' left justify transmit data
shl X,#1 wc ' balance clock pulse width adjustment
BSPIOlp muxc OUTA,spiout ' send next bit of data out
xor OUTA,spisck ' clock low
shl X,#1 wc ' assume msb first
xor OUTA,spisck ' clock high
djnz R1,#BSPIOlp
djnz tos,#BBlp
jmp #DROP2
BSPIWR byte _WORD,(@_BSPIWR+s)>>8,@_BSPIWR+s
byte XCALL,xLOADMOD,EXIT
{HELP ESPIO ( send -- receive ) ( A: miso mosi sck )
COGREGS: 0=sck 1=mosi 2=miso 3=cnt 4=cs
*** ENHANCED SERIAL PERIPHERAL INPUT OUTPUT MODULE ***
Transfers 1 to 32 bits msb first
Transmit data does not need to be left justified to be ready for transmission
Receive data is in correct format
Data is shifted in and out while the clock is low
The clock is left low between transfers unless a chip select mask is specified
}
org _RUNMOD
'
' ESPIO ( send -- receive ) ( A: miso mosi sck )
_ESPIO
andn OUTA,scs ' chip select low
mov R1,#32
sub R1,scnt
shl tos,R1 ' left justify transmit data
mov R1,scnt
ESPIOlp andn OUTA,sck ' clock low
shl sdat,#1 wc ' assume msb first
test miso,INA wz ' test data from device while clock is low
muxc OUTA,mosi ' send next bit of data out
if_nz or sdat,#1 ' now assemble data (also setup time for mosi)
or OUTA,sck ' clock high
djnz R1,#ESPIOlp
tjnz scs,#ESxt ' leave with clock high if CS mask specified
andn OUTA,sck ' leave with clock low
ESxt or OUTA,scs ' chip select high
jmp unext
ESPIO byte _WORD,(@_ESPIO+s)>>8,@_ESPIO+s
' this next line is common to other modules XCALL,xLOADMOD
aLOADMOD byte _WORD,_RUNMOD>>8,_RUNMOD,_BYTE,loadsz,XOP,pLOADMOD,EXIT
org _RUNMOD
{HELP SSD ( send cnt -- ) ( A: miso mosi sck )
SSD module added for fast SSD2119 SPI operations
COGREGS: 0=sck 1=mosi 2=miso 3=cnt 4=mode }
_SSD
SSDREP mov X,tos+1
shl X,#7 ' left justify but leave msb zero (control byte)
call #SSD8
call #SSD8D
call #SSD8D
djnz tos,#SSDREP
jmp #DROP2
SSD8D or X,#1 ' move 1 into msb = data
ror X,#1
SSD8 andn OUTA,scs ' chip select low
mov R1,scnt
SSDlp andn OUTA,sck ' clock low
shl X,#1 wc ' assume msb first
muxc OUTA,mosi ' send next bit of data out
or OUTA,sck ' clock high
djnz R1,#SSDlp
or OUTA,scs ' chip select high
SSD8D_ret
SSD8_ret ret
SSD byte _WORD,(@_SSD+s)>>8,@_SSD+s
byte XCALL,xLOADMOD,EXIT
{HELP SPIO ( send -- receive ) ( A: miso mosi sck )
COGREGS: 0=sck 1=mosi 2=miso 3=cnt
*** SERIAL PERIPHERAL INPUT OUTPUT MODULE ***
Transfers 1 to 32 bits msb first
Transmit data must be left justified ready for transmission
Receive data is in correct format
Data is shifted in and out while the clock is low
The clock is left low between transfers
}
org _RUNMOD
' COGREGS: 0=sck 1=mosi 2=miso 3=cnt
' SPIO ( send -- receive ) ( A: miso mosi sck )
_SPIO mov R1,scnt
or DIRA,mosi ' MOSI must be an output
SPIOlp andn OUTA,sck ' clock low
shl sdat,#1 wc ' assume msb first
test miso,INA wz ' test data from device while clock is low
muxc OUTA,mosi ' send next bit of data out
if_nz or sdat,#1 ' now assemble data (also setup time for mosi)
or OUTA,sck ' clock high
djnz R1,#SPIOlp
andn OUTA,sck ' leave with clock low
jmp unext
SPIO byte _WORD,(@_SPIO+s)>>8,@_SPIO+s
byte XCALL,xLOADMOD,EXIT
{ org REG0
sck res 1
mosi res 1
miso res 1
scs res 1
scnt res 1
}
{ org _RUNMOD
' COGREGS: 0=sck 1=mosi 2=miso 3=delay 4=scnt
' SPIOD ( send -- receive ) ( A: miso mosi sck )
_SPIOD mov R1,scnt
or DIRA,mosi
SPIODlp andn OUTA,sck ' clock low
shl sdat,#1 wc ' assume msb first
test miso,INA wz ' test data from device while clock is low
muxc OUTA,mosi ' send next bit of data out
if_nz or sdat,#1 ' now assemble data (also setup time for mosi)
or OUTA,sck ' clock high
mov X,scs ' use reg3 for delay value
spiodly djnz X,#spiodly
djnz R1,#SPIODlp
andn OUTA,sck ' leave with clock low
jmp unext
SPIOD byte _WORD,(@_SPIOD+s)>>8,@_SPIOD+s
byte XCALL,xLOADMOD,EXIT
}
' start,sing/diff,d2,d1,d0,x,x -- 11..0
org _RUNMOD
' COGREGS: 0=sck 1=mosi 2=miso 3=cs
' MCP32 ( send -- receive ) ( A: miso mosi sck )
' send = s/d+ch
_MCP32 or sdat,#$18 ' add start bit + single mode
shl sdat,#27 ' left justify
or DIRA,mosi ' make sure mosi is an output
andn OUTA,scs ' assert ce
mov R1,#19 ' clock out 7 bits then read 12
mcplp andn OUTA,sck ' clock low
cmp R1,#14 wc ' if mosi = miso then switch to input after 5 clocks
if_c andn DIRA,miso
shl sdat,#1 wc ' assume msb first
test miso,INA wz ' test data from device while clock is low
muxc OUTA,mosi ' send next bit of data out
if_nz or sdat,#1 ' now assemble data (also setup time for mosi)
or OUTA,sck ' clock high
mov X,#1
:dly djnz X,#:dly
djnz R1,#mcplp
andn OUTA,sck ' leave with clock low
or OUTA,scs ' ce high
and sdat,mmask
jmp unext
mmask long $0FFF
MCP32 byte _WORD,(@_MCP32+s)>>8,@_MCP32+s
byte XCALL,xLOADMOD,EXIT
{HELP SDRD ( dst char -- firstPos charcnt \ read block from SD into memory while scanning for special char )
dst is a 32 bit SD-card address 0..4GB, char is the character to scan for while, reading in the block.
NOTE: ensure MOSI is set as an output high from caller by 1 COGREG@ OUTSET
This is just the low-level block read once the SD card has been setup, so it just reads a sector into the dst
There is also a scan character that it will look for and return it's first position and how many were found
}
org _RUNMOD
_SDRD
mov X,tos+1 ' dst --> X
mov R2,dst1 '$200 ' R2 = 512 bytes
SDRDSClp mov R1,#8 ' 8-bits
SDRDSCbits andn OUTA,sck ' clock low
test miso,INA wc ' test data from device while clock is low
rcl R0,#1 ' now assemble data (also setup time for mosi)
or OUTA,sck ' clock high
djnz R1,#SDRDSCbits
andn OUTA,sck ' leave with clock low
wrbyte R0,X ' write byte to destination
and R0,#$FF ' only want to compare a byte value
cmp R0,tos wz ' compare byte with char unsigned for equality
if_z add ACC,#1 ' found one and increment count
if_z cmp ACC,#1 wz ' if match and count = 1 (first occurrence)
if_z mov tos+1,X ' then save dst (tos+2) to firstpos (tos)
add X,#1 ' dst = dst+1
djnz R2,#SDRDSClp ' next
call #POPX ' discard "char"
jmp #PUSHACC ' push char count and clear ACC
' Load the SDSCAN read module (13us)
SDRD byte _WORD,(@_SDRD+s)>>8,@_SDRD+s
byte XCALL,xLOADMOD,EXIT
{
' moved to SDCARD.fth MJB
WORD scancnt,scanpos
BYTE scanch
--- Read in one block of 512 bytes from SD to dst
pri (SDRD) ( dst -- )
\ BYTE scanch holds the char to scan for
\ gives number of character matches found in WORD scancnt
\ autoincrements on each call, use scancnt W~ to init to 0 if needed
\ position of first match in WORD scanpos
[SDRD] 1 COGREG@ OUTSET scanch C@ RUNMOD
scancnt W+! scanpos W@ 0= IF scanpos W! ELSE DROP THEN ' to catch the earliest over many block reads - use scanpos W~ to init
;
}
' SD MODULE
org _RUNMOD
' Write a block to the SD card - 512 bytes
' SDWR ( src cnt -- ;write block from memory to SD )
_SDWR
or DIRA,mosi
SDWRlp rdbyte R0,tos+1 ' read next byte from source
add tos+1,#1 ' increment source address
shl R0,#24 ' left justify
mov R1,#8 ' send 8 bits
SDWRbits andn OUTA,sck ' clock low
shl R0,#1 wc ' assume msb first
muxc OUTA,mosi ' send next bit of data out
or OUTA,sck ' clock high
djnz R1,#SDWRbits
andn OUTA,sck ' leave with clock low
djnz tos,#SDWRlp ' next byte
jmp #DROP2
' Load the SD write module
SDWR byte _WORD,(@_SDWR+s)>>8,@_SDWR+s
byte XCALL,xLOADMOD,EXIT
{ *** 32 channel 8-bit PWM *** }
' [PWM32] loads the PWM32 module into the cog ready for a RUNMOD
PWM32 byte _WORD,(@_PWM32+s)>>8,@_PWM32+s
byte XCALL,xLOADMOD,EXIT
' kuroneko's 7.6kHz version of the 32 channel PWM module
' ( table waitcnt -- )
org _RUNMOD ' Compile for RUNMOD area in cog
_PWM32 movi ctrb, #%0_11111_000 ' LOGIC.always
mov frqb, tos+1 ' table base address
shr frqb, #1{/2} ' divided by 2 (expected to be 4n)
mov cnt,#5{14}+2*4+23 ' minimal entry delay
add cnt,cnt
mov phsb,#0 ' preset (not optional, 8n)
pwmlp32 and phsb,wrap32 ' $0400 to $0000 transition |
rdlong X,phsb ' read from index + 2*table/2 | need to be back-to-back
waitcnt cnt,tos ' |
mov outa,X ' update outputs
add phsb,#4 ' update read ptr |
rdlong X,phsb ' read from index + 2*table/2 | need to be back-to-back
add phsb,#4 ' update read ptr
waitcnt cnt,tos ' |
mov outa,X ' update outputs
jmp #pwmlp32
wrap32 long 256 * 4 -1
{ PWM32 TIMING SAMPLE
}
' PWM32! SETUP TABLE MODULE
' this module is run from the controlling cog whereas the PWM32 runtime is in a dedicated cog
org _RUNMOD
' _PWM32! ( duty8 mask table -- ) ' 104us (LOADMOD takes 18.8us)
_PWMST32 mov R2,#256 ' scan through all 256 slices
add tos,endtbl ' start from end (optimize hub access)
add tos+2,#1 ' compensate for cmp op so that $80 = 50 %, $100 = 100 %
pwmstlp32 rdlong X,tos ' read one 1/256 slice of 32 channels
cmp R2,tos+2 wc ' is duty8 > R2
muxc X,tos+1 ' set or clear the bit(s)
wrlong X,tos ' update slice
sub tos,#4 ' next long
djnz R2,#pwmstlp32 ' terminate on wrap
jmp #DROP3
endtbl long 256 * 4 -4 ' offset to last long of table
' [PWM32!] Load the PWM32! module which is used to setup the PWM table
PWMST32 byte _WORD,(@_PWMST32+s)>>8,@_PWMST32+s
byte XCALL,xLOADMOD,EXIT
' PLOT MODULE
' Used for VGA/TV or LCD graphics
' pixshift is always a multiple of two, 512 pixels/line = 6 etc
'
org _RUNMOD
' PLOT ( x y -- )
_PLOT shl tos,pixshift ' n^2 bytes/Y line
mov X,tos+1
shr tos+1,#3 ' byte offset in line
add tos,tos+1 ' byte offset in frame
add tos,pixeladr ' byte address in memory
and X,#7 ' get bit mask
mov tos+1,#1
shl tos+1,X
jmp #SET
' [PLOT]