forked from zuloloxi/mecrisp-ice
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME
899 lines (650 loc) · 34 KB
/
README
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
-------------------------------------------------------------------------------
Mecrisp-Ice - A conveniently enhanced fork of Swapforth by James Bowman
It makes your Lattice Icestick FPGA development board
to behave just like a microcontroller.
The original Swapforth and J1a processor implementation can be found here:
http://www.excamera.com/sphinx/article-j1a-swapforth.html
I would not have been possible without the first open-source FPGA toolchain:
http://www.clifford.at/icestorm/
Many, many thanks to James Bowman and the whole Icestorm team !
http://mecrisp.sourceforge.net/
-------------------------------------------------------------------------------
HIC SUNT DRACONES - HIC SUNT DRACONES - HIC SUNT DRACONES
This is the first experimental release, so beware: Monsters may be inside !
-------------------------------------------------------------------------------
Shortly after Clifford Wolff, Mathias Lasser and Cotton Seed managed to build
the first working completely open-source FPGA toolchain for the iCE40-HX1K,
James Bowman started porting his elegant J1 processor design.
I have been involved in testing and enhanced the resulting monumental work
with stronger optimisations and a handfull of features for convenience.
-------------------------------------------------------------------------------
What you need:
* A Lattice Icestick with an iCE40-HX1K FPGA
http://www.latticesemi.com/icestick
* Or a Nandland Go with iCE40-HX1K FPGA
https://www.nandland.com/goboard/introduction.html
* Or a Lattice HX8K breakout board with an iCE40-HX8K FPGA
* The Iceprog tool to flash the included binary
http://www.clifford.at/icestorm/
* A terminal, picocom is fine.
-------------------------------------------------------------------------------
Which board for you ?
If you just wish to play with a stack processor,
if you have small ideas,
if you desire to have IrDA communication,
if you wish a cheap, cool looking board,
if you are fine without tinkering with additional logic
--> HX1K Icestick is your choice.
If you wish to experiment with VGA video,
if you like 7-segment displays,
if you need buttons on your board
--> HX1K Nandland Go should be the right for you.
If you have large ideas in Forth,
if you need a lot of IO pins,
if you wish to wire in additional peripherals, opcodes or whatever you imagine,
if you love to have single cycle multiplier and barrel shifters
--> HX8K breakout board will give you a nice time.
-------------------------------------------------------------------------------
Basic usage, same for HX1K and HX8K:
Flash the binary:
iceprog -b j1a.bin
Open a terminal:
picocom -b 115200 /dev/ttyUSB$n --imap lfcrlf,crcrlf --omap delbs,crlf --send-cmd "ascii-xfr -s -l 30 -n"
Toggle DTR line to Reset by pressing Crtl+A Ctrl+T Crtl+A Ctrl+T
You should get a welcome message.
If you hard crash it, iceprog -t or a power cycle should recover.
-------------------------------------------------------------------------------
Some notes for Forth users new to this target and its peripheral possibilities:
The Icestick has 8 kb of initialised RAM which is mapped from address
$0000 to $1FFF and a SPI flash to store the FPGA bitstream and additional
user generated memory images.
Data and return stack are 16 elements deep. James implemented them as
part of the CPU itself, so they are not accessible through memory.
Pinout and board layout:
/--------------------------------------
/ Header 1: 76543210-+
/ ________ ++
/ | | R --
[USB] FT | FPGA | R G R 73 Ir
[USB] DI | | R 62 DA
\ |________| 51
\ 40
\ Header 2: 01234567-+
\--------------------------------------
Numbers are bit numbers
+ is 3.3 V - is GND
G Green LED R Red LEDs
There is a separate IO address space, with those registers available:
Addr Bit READ WRITE
0001 0 PMOD in
0002 1 PMOD out PMOD out
0004 2 PMOD dir PMOD dir
0008 3 misc.out misc.out
0010 4 header 1 in
0020 5 header 1 out header 1 out
0040 6 header 1 dir header 1 dir
0080 7 eint
0100 8 header 2 in
0200 9 header 2 out header 2 out
0400 10 header 2 dir header 2 dir
0800 11 dint
1000 12 UART RX UART TX
2000 13 misc.in
4000 14 ticks clear ticks
8000 15
Contents of misc.out and misc.in:
Bitmask Bit misc.out misc.in
0001 0 SPI CS UART Ready to Transmit
0002 1 SPI MOSI UART Character received
0004 2 SPI SCK SPI MISO
0008 3 IrDA-TXD IrDA-RXD
0010 4 IrDA-Sleep RTS
0020 5 CTS Random
0040 6 Green LED
0080 7 Red LED
0100 8 Red LED
0200 9 Red LED
0400 10 Red LED
If you are already familiar with MSP430 chips,
you will know this IO port style:
* The IN register gives the current electrical state
* The contents of the OUT registers determine what level the outputs should be
* The DIR register let you switch a pin to be an output by writing an one into
You can set two registers at once if you OR together their addresses.
255 $440 io! should set all header pins as outputs.
Inputs can ORed together the same way and give an ORed result.
You can detect short-circuited pins -
for example if a pin is set to output and low, but shortened to Vcc,
then the OUT register will read back low, as set by you, but the
IN register will read high for that pin.
Misc.out and misc.in are a mixed back of wires and flags available.
No fear to destroy the IrDA transceiver with too long pulses as it turns off
the IR LED itself when IrDA-TXD is high for more than 50 us.
The UART data register is for both incoming and outgoing data,
a read from it will clear the "Character received" flag
and you should only write to it when "Ready to Transmit" is set.
Ticks contains a 16 bit cycle counter that counts up with 48 MHz and
you can set it to any value you wish by writing to it.
Memory location $1FFE is an interrupt vector for the ticks counter overflow.
You can place an opcode there, perhaps ALU Exit ($608C) or a JMP to a handler.
Interrupts can be enabled with eint and disabled with dint.
-------------------------------------------------------------------------------
Notes on HX8K:
--------------
This feels very similiar to Mecrisp-Ice on HX1K, just with a few differences:
+ Double amount of memory: 16 kb instead of 8 kb
+ Double stack depth: 32 elements each instead of 16
+ Barrel shifter for single cycle lshift rshift arshift
+ Single cycle multiplication
+ Fast opcodes for 1+ and 1-
+ rdepth
+ 8 LEDs instead of 5
+ Lots of gates free for experiments
- 36 MHz only
- No IrDA
- Variable @ needs 2 instructions and 5 cycles instead of 1 instruction and 2 cycles
The peripheral map is the same, but the IN, OUT and DIR registers
are up to 16 bits wide, with the following connections:
$0001 Port A IN $0010 Port B IN $0100 Port C IN
$0002 Port A OUT $0020 Port B OUT $0200 Port C OUT
$0004 Port A DIR $0040 Port B DIR $0400 Port C DIR
Red LEDs
76543210
1.2V 3.3V oo oo oo
1.2V B13 oo oo oo
A12 B12 oo ________ oo oo
GND GND oo | | oo oo
A11 B11 oo | FPGA | oo oo
A10 B10 oo | | oo oo
A9 B9 oo |________| oo oo
GND GND oo oo oo
A8 B8 oo oo oo
A7 B7 oo oo oo
A6 B6 oo Jumper config: oo oo
GND GND oo oo oo
A5 B5 oo | || oo oo
A4 B4 oo oo oo
A3 B3 oo Green oo oo
GND GND oo LED oo oo
A2 B2 oo FT oo oo
A1 B1 oo DI oo oo
A0 B0 oo oo oo
GND GND oo [USB] oo oo
[USB]
Port C is currently unconnected, you can wire the bits as you wish
in the constraints PCF file.
Ticks contains a 16 bit cycle counter that counts up with 36 MHz and
you can set it to any value you wish by writing to it.
Memory location $3FFE is an interrupt vector for the ticks counter overflow.
You can place an opcode there, perhaps ALU Exit ($608C) or a JMP to a handler.
Interrupts can be enabled with eint and disabled with dint.
-------------------------------------------------------------------------------
Notes on Nandland Go:
---------------------
S4 is Reset button, as DTR line is not connected on this board.
Addr Bit READ WRITE
0001 0 PMOD in
0002 1 PMOD out PMOD out
0004 2 PMOD dir PMOD dir
0008 3 misc.out misc.out
0010 4 VGA Colours
0020 5 VGA HSYNC
0040 6 VGA VSYNC
0080 7 Segments Segments
0100 8
0200 9
0400 10
0800 11
1000 12 UART RX UART TX
2000 13 misc.in
4000 14 ticks clear ticks
8000 15
Contents of misc.out and misc.in:
Bitmask Bit misc.out misc.in
0001 0 SPI CS UART Ready to Transmit
0002 1 SPI MOSI UART Character received
0004 2 SPI SCK SPI MISO
0008 3 Green LED 1 Random
0010 4 Green LED 2 S1
0020 5 Green LED 3 S2
0040 6 Green LED 4 S3
Note that you can OR together the VGA lines.
VSYNC HSYNC Blue 2 Blue 1 Blue 0 Green 2 Green 1 Green 0 Red 2 Red 1 Red 0
$10: 256 128 64 32 16 8 4 2 1
$20: 512
$40: 1024
So by writing IO Register $60, you can set HSYNC and VSYNC independently
from the colour register bits. If you prefer to have all VGA signals
in one register, use IO port $70.
Ticks contains a 16 bit cycle counter that counts up with 25 MHz and
you can set it to any value you wish by writing to it.
Memory location $1FFE is an interrupt vector for the ticks counter overflow.
You can place an opcode there, perhaps ALU Exit ($608C) or a JMP to a handler.
Interrupts can be enabled with eint and disabled with dint.
-------------------------------------------------------------------------------
Special features included in Mecrisp-Ice:
-----------------------------------------
You can save the complete current memory contents into the SPI flash
sectors 1 to 63. Sector 0 contains the FPGA bitstream, sector 1 will be
loaded automatically on startup if you save a memory image into this.
sector# load
sector# save
sector# erase
There is a variable "init" which is executed after loading an image.
So if you wish to create a turnkey application, prepare everything in RAM
and type:
' fireworks init !
1 save
Replace fireworks with whatever you wish to be executed on startup.
Nothing is executed if init contains a zero, which is the default.
If you are not sure if it will work properly, save to any other sector
and load manually. The init mechanism works the same on all sectors.
On HX8K: Sectors 0, 1 and 2 contain the bitstream.
Sector 3 will be loaded automatically if available.
The Nandland Go has a smaller SPI Flash with four sectors only:
0: Bitstream
1: Autoload
2: Free
3: Free
-----------------------------------------
For your convenience, some introspection features are preloaded for default.
Things to try:
0 8192 dump
insight
see +
They will be removed by typing "new" so that you have more space available.
-----------------------------------------
Inline optimisations and constant folding are included !
-------------------------------------------------------------------------------
Main differences to Mecrisp and Mecrisp-Stellaris:
Unlike Mecrisp and Mecrisp-Stellaris, this is running completely
in RAM memory. So there is no need for special memory handling !
You can use CREATE with DOES> and if you need a buffer,
just CREATE ... ALLOT it.
By the way: If you save a memory image, the last contents of the variables
are saved during the process and reloaded with the image. Variables are
initialised, but there is no logic to reinitialise them on Reset to the
values assigned at compilation.
-------------------------------------------------------------------------------
If you wish to build the whole package yourself:
* Gforth
* Freepascal
* Yosys for synthesis
* Arachne-PNR for place and route
* Icestorm tools for bitstream generation
... and their dependencies.
In a nutshell, you need to type:
compile
iceprog -b j1a.bin
That's all.
;------------------------------------------------------------------------------
Here comes a word list, -- Glossary --
with short descriptions of all currently included words:
View it with fixed-width font !
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Terminal-IO
;------------------------------------------------------------------------------
emit? ( -- Flag ) Ready to send a character ?
key? ( -- Flag ) Checks if a key is waiting
key ( -- Char ) Waits for and fetches the pressed key
emit ( Char -- ) Emits a character.
;------------------------------------------------------------------------------
; Stack Jugglers
;------------------------------------------------------------------------------
Single-Jugglers:
depth ( -- +n ) Gives number of single-cell stack items.
rdepth ( -- +n ) HX8K only: Number of items on return stack.
nip ( x1 x2 -- x2 )
drop ( x -- )
rot ( x1 x2 x3 -- x2 x3 x1 )
-rot ( x1 x2 x3 -- x3 x1 x2 )
swap ( x1 x2 -- x2 x1 )
tuck ( x1 x2 -- x2 x1 x2 )
over ( x1 x2 -- x1 x2 x1 )
?dup ( x -- 0 | x x )
dup ( x -- x x )
>r ( x -- ) (R: -- x )
r> ( -- x ) (R: x -- )
r@ ( -- x ) (R: x -- x )
rdrop ( -- ) (R: x -- )
Double-Jugglers: They perform the same for double numbers.
2drop ( x1 x2 -- )
2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
2over ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )
2dup ( x1 x2 -- x1 x2 x1 x2 )
;------------------------------------------------------------------------------
; Logic
;------------------------------------------------------------------------------
arshift ( x1 u -- x2 ) Arithmetric right-shift of u bit-places
rshift ( x1 u -- x2 ) Logical right-shift of u bit-places
lshift ( x1 u -- x2 ) Logical left-shift of u bit-places
invert ( x1 -- x2 ) Invert all bits
not ( x1 -- x2 ) Invert all bits = Bitwise not
xor ( x1 x2 -- x3 ) Bitwise Exclusive-OR
or ( x1 x2 -- x3 ) Bitwise OR
and ( x1 x2 -- x3 ) Bitwise AND
false ( -- 0 ) False-Flag
true ( -- -1 ) True-Flag
;------------------------------------------------------------------------------
; Arithmetic for single numbers
;------------------------------------------------------------------------------
/mod ( n1 n2 -- n3 n4 ) n1 / n2 = n4 rem n3
mod ( n1 n2 -- n3 ) n1 / n2 = remainder n3
/ ( n1 n2 -- n3 ) n1 / n2 = n3
* ( u1|n1 u2|n2 -- u3|n3 ) 16*16 = 16 Multiplication
min ( n1 n2 -- n1|n2 ) Keeps smaller of top two items
max ( n1 n2 -- n1|n2 ) Keeps greater of top two items
umin ( u1 u2 -- u1|u2 ) Keeps unsigned smaller
umax ( u1 u2 -- u1|u2 ) Keeps unsigned greater
1- ( u1|n1 -- u2|n2 ) Subtracts one, optimized
1+ ( u1|n1 -- u2|n2 ) Adds one, optimized
2* ( n1 -- n2 ) Arithmetric left-shift
2/ ( n1 -- n2 ) Arithmetric right-shift
abs ( n -- u ) Absolute value
negate ( n1 -- n2 ) Negate
sgn ( u1 n1 -- n2 ) Give u1 the sign of n2
- ( u1|n1 u2|n2 -- u3|n3 ) Subtraction
+ ( u1|n1 u2|n2 -- u3|n3 ) Addition
;------------------------------------------------------------------------------
; Arithmetic involving double numbers
;------------------------------------------------------------------------------
um* ( u1 u2 -- ud ) 16*16 = 32 Multiplication
um/mod ( ud u1 -- u2 u3 ) ud / u1 = u3 remainder u2
m+ ( d1 n -- d2 ) Addition of a double with a single
m* ( n1 n2 -- d ) n1 * n2 = d
fm/mod ( d n1 -- n2 n3 ) d / n1 = n3 remainder r2 floored
sm/rem ( d n1 -- n2 n3 ) d / n1 = n3 remainder r2 symmetric
*/ ( n1 n2 n3 -- n4 ) n1 * n2 / n3 = n4
*/mod ( n1 n2 n3 -- n4 n5 ) n1 * n2 / n3 = n5 remainder n4
d2* ( d1 -- d2 ) Arithmetric left-shift
dabs ( d -- ud ) Absolute value
dnegate ( d1 -- d2 ) Negate
d- ( ud1|d1 ud2|d2 -- ud3|d3 ) Subtraction
d+ ( ud1|d1 ud2|d2 -- ud3|d3 ) Addition
s>d ( n -- d ) Makes a signed single number double length
;------------------------------------------------------------------------------
; Comparisions
;------------------------------------------------------------------------------
u<= ( u1 u2 -- flag ) Unsigned comparisions
u>= ( u1 u2 -- flag )
u> ( u1 u2 -- flag )
u< ( u1 u2 -- flag )
<= ( n1 n2 -- flag ) Signed comparisions
>= ( n1 n2 -- flag )
> ( n1 n2 -- flag )
< ( n1 n2 -- flag )
0> ( n -- flag ) Positive ?
0< ( n -- flag ) Negative ?
0<> ( x -- flag )
0= ( x -- flag )
<> ( x1 x2 -- flag )
= ( x1 x2 -- flag )
d0= ( d -- flag )
within ( x1 x2 x3 -- ? ) Check if x1 is within x2 and x3.
;------------------------------------------------------------------------------
; Tools for number input
;------------------------------------------------------------------------------
number ( c-addr len -- 0 )
-- n 1 )
-- n-low n-high 2 )
Tries to convert a string to a number.
;------------------------------------------------------------------------------
; Number base
;------------------------------------------------------------------------------
binary ( -- ) Sets base to 2
decimal ( -- ) Sets base to 10
hex ( -- ) Sets base to 16
base ( -- a-addr ) Base variable address
;------------------------------------------------------------------------------
; Memory access
;------------------------------------------------------------------------------
cmove ( c-addr1 c-addr2 u -- ) Moves backward
cmove> ( c-addr1 c-addr2 u -- ) Moves forward
move ( c-addr1 c-addr2 u -- ) Moves u Bytes in Memory
fill ( c-addr u c ) Fill u Bytes of Memory with value c
constant name ( u|n -- ) Makes a single constant.
variable name ( u|n -- ) Makes an initialized single variable
2@ ( a-addr -- ud|d ) Fetches double number from memory
2! ( ud|d a-addr -- ) Stores double number in memory
@ ( a-addr -- u|n ) Fetches single number from memory
! ( u|n a-addr -- ) Stores single number in memory
+! ( u|n a-addr -- ) Add to memory location
c@ ( c-addr -- char ) Fetches byte from memory
c! ( char c-addr ) Stores byte in memory
IO memory area:
io@ ( c-addr -- x ) Fetches from IO register
io! ( x c-addr -- ) Stores into IO register
xor! ( mask c-addr -- ) Toggle bits
bic! ( mask c-addr -- ) Clear BIts
bis! ( mask c-addr -- ) Set BIts
;------------------------------------------------------------------------------
; Strings and beautiful output
;------------------------------------------------------------------------------
String routines:
type ( c-addr length -- )
Prints a string.
rtype ( c-addr length u -- )
Prints a string in a field u characters wide.
s" Hello" Compiles a string and
( -- c-addr length )
gives back its address and length when executed.
." Hello" Compiles a string and
( -- )
prints it when executed.
( Comment ) Ignore Comment
\ Comment Comment to end of line
cr ( -- ) Emits line feed
bl ( -- 32 ) ASCII code for Space
space ( -- ) Emits space
spaces ( n -- ) Emits n spaces if n is positive
accept ( c-addr maxlength -- length ) Read input into a string.
Counted string routines:
count ( cstr-addr -- c-addr length )
Convert counted string into addr-length string
Pictured numerical output:
[char] * Compiles code of following char
( -- char ) when executed
char * ( -- char ) gives code of following char
hold ( char -- ) Adds character to pictured number
output buffer from the front.
sign ( n -- ) Add a minus sign to pictured number
output buffer, if n is negative
#S ( ud1|d1 -- 0 0 ) Add all remaining digits
from the double length number to output buffer
# ( ud1|d1 -- ud2|d2 ) Add one digit from the
double length number to output buffer
#> ( ud|d -- c-addr len )
Drops double-length number and finishes
pictured numeric output ready for type
<# ( -- ) Prepare pictured number output buffer
u. ( u -- ) Print unsigned single number
. ( n -- ) Print single number
ud. ( ud -- ) Print unsigned double number
d. ( d -- ) Print double number
u.r ( u width -- ) Print unsigned right aligned
.r ( n width -- ) Print signed right aligned
d.r ( d width -- ) Print double signed right aligned
buf0 ( -- a-addr ) Start of number output buffer
buf ( -- a-addr ) End of number output buffer
hld ( -- a-addr ) Variable with current position
Deep insights:
words ( -- ) Prints list of defined words.
.x2 ( c -- ) Prints 8 bit unsigned in hex base
.x ( u -- ) Prints 16 bit unsigned in hex base
This is independent of number subsystem.
;------------------------------------------------------------------------------
; User input and its interpretation
;------------------------------------------------------------------------------
tib ( -- c-addr ) Input buffer
pad ( -- c-addr ) Location to hold temporary data
refill ( -- ? ) Refill input buffer, return true if successful
source! ( c-addr len -- ) Change source
source ( -- c-addr len ) Current source
>in ( -- addr ) Variable with current offset into source
/string ( c-addr1 u1 n -- c-addr2 u2 ) Cut n leading characters
parse-name ( -- c-addr len ) Get next token from input buffer
parse ( char -- c-addr len )
Cuts anything delimited by char out of input buffer
evaluate ( any addr len -- any ) Interpret given string
quit ( many -- ) (R: many -- ) Resets Stacks
abort ( many -- ) (R: many -- ) Print ? and quit
;------------------------------------------------------------------------------
; Dictionary expansion
;------------------------------------------------------------------------------
align ( -- ) Aligns dictionary pointer
aligned ( c-addr -- a-addr ) Advances to next aligned address
cell+ ( x -- x+2 ) Add size of one cell
cells ( n -- 2*n ) Calculate size of n cells
allot ( n -- ) Tries to advance Dictionary Pointer by n bytes
here ( -- a-addr|c-addr )
Gives current position in Dictionary
, ( u|n -- ) Appends a single number to dictionary
c, ( char -- ) Appends a byte to dictionary
unused ( -- u ) How many free space is still available ?
cornerstone name Create a permanent dictionary wayback point
new Core wayback point.
;------------------------------------------------------------------------------
; Dictionary expansion (more internal)
;------------------------------------------------------------------------------
s, ( c-addr len -- ) Inserts a string with a maximum
of 255 characters without runtime
sliteral ( c-addr len -- ) Insert a string with runtime
literal ( u|n -- ) Compiles a literal
compile, ( a-addr -- ) Compiles a call to a subroutine
forth ( -- a-addr ) Variable with entry point for dictionary
ahead ( -- a-addr ) Prepare a forward jump
;------------------------------------------------------------------------------
; Flags and inventory
;------------------------------------------------------------------------------
immediate ( -- ) Makes current definition immediate.
foldable ( n -- ) Current word becomes foldable with n constants
sfind ( c-addr len -- c-addr len 0 | a-addr flags )
Searches for a string in Dictionary.
;------------------------------------------------------------------------------
; Compiler essentials
;------------------------------------------------------------------------------
execute ( a-addr -- ) Calls subroutine
recurse ( -- ) Lets the current definition call itself
' name ( -- a-addr ) Tries to find name in dictionary
gives back executable address
['] name ( -- a-addr) Tick that compiles the executable address
of found word as literal
postpone name ( -- ) Helps compiling immediate words.
does> ( -- ) executes: ( -- a-addr )
Gives address to where you have stored data.
create name ( -- ) Create a definition with default action
>body ( a-addr -- a-addr ) Address of data field after create
state ( -- a-addr ) Address of state variable
] ( -- ) Switch to compile state
[ ( -- ) Switch to execute state
; ( -- ) Finishes new definition
: name ( -- ) Opens new definition
:noname ( -- a-addr ) Opens new definition without name
;------------------------------------------------------------------------------
; Control structures
;------------------------------------------------------------------------------
Decisions:
flag if ... then
flag if ... else ... then
then ( -- ) This is the common
else ( -- ) flag if ... [else ...] then
if ( flag -- ) structure.
Case:
n case
m1 of ... endof
m2 .. ... .....
all others
endcase
case ( n -- n ) Begins case structure
of ( m -- ) Compares m with n, choose this if n=m
endof ( -- ) End of one possibility
endcase ( n -- ) Ends case structure, discards n
Indefinite Loops:
begin ... again
begin ... flag until
begin ... flag while ... repeat
repeat ( -- ) Finish of a middle-flag-checking loop.
while ( flag -- ) Check a flag in the middle of a loop
until ( flag -- ) begin ... flag until
loops as long flag is true
again ( -- ) begin ... again
is an endless loop
begin ( -- )
Definite Loops:
limit index do ... [one or more leave(s)] ... loop
?do ... [one or more leave(s)] ... loop
do ... [one or more leave(s)] ... n +loop
?do ... [one or more leave(s)] ... n +loop
j ( -- u|n ) Gives second loop index
i ( -- u|n ) Gives innermost loop index
unloop (R: old-limit old-index -- )
Drops innermost loop structure,
pops back old loop structures to loop registers
exit ( -- ) Returns from current definition.
leave ( -- ) (R: old-limit old-index -- )
Leaves current innermost loop promptly
+loop ( u|n -- )
(R: unchanged | old-limit old-index -- )
Adds number to current loop index register
and checks whether to continue or not
loop ( -- )
(R: unchanged | old-limit old-index -- )
Increments current loop index register by one
and checks whether to continue or not.
?do ( Limit Index -- )
(R: unchanged | -- old-limit old-index )
Begins a loop if limit and index are not equal
do ( Limit Index -- )
(R: -- old-limit old-index )
Begins a loop
bounds ( addr len -- limit index )
Calculate values to loop over a string
;------------------------------------------------------------------------------
; SPI and low-level flash memory access
;------------------------------------------------------------------------------
spix ( c1 -- c2 ) Exchange one byte on SPI
>spi ( c -- ) Send one byte to SPI
spi> ( -- c ) Receive one byte from SPI
idle ( -- ) Set SPI flash to idle state
spiwe ( -- ) Write enable on SPI flash
waitspi ( -- ) Wait for write or erase to finish
;------------------------------------------------------------------------------
; Memory images
;------------------------------------------------------------------------------
Sectors from 1 to 63. Sector 1 is automatically loaded after Reset.
load ( sector# -- ) Loads an image
save ( sector# -- ) Saves an image
erase ( sector# -- ) Erase an image
init ( -- a-addr ) Variable containing either zero
or the address of a turnkey definition
which is executed automatically
;------------------------------------------------------------------------------
; Misc hardware
;------------------------------------------------------------------------------
leds ( x -- ) Display bitpattern on LEDs
ms ( u -- ) Wait u milliseconds
ticks ( -- u ) Read current ticks
now ( -- ) Clear tick counter
delay ( u -- ) Wait until u ticks are reached
randombit ( -- 0 | 1 ) Gives a random bit
random ( -- x ) Gives a random number
eint? ( -- ? ) Are interrupts enabled ?
eint ( -- ) Enable ticks counter overflow interrupt
dint ( -- ) Disable interrupt
;------------------------------------------------------------------------------
; Insight tools that are gone after NEW
;------------------------------------------------------------------------------
.s ( many -- many ) Prints stack contents
dump ( addr len -- ) Dump memory contents
insight ( -- ) Complete printout of dictionary structure
name. ( a-addr -- ) If this is the code-start of a definition,
try to print its name.
memstamp ( a-addr -- ) Show memory location nicely
disasm-$ ( -- a-addr ) Variable for current disasm position
disasm-cont ( -- a-addr ) Variable: Continue up to this position
disasm-step ( -- ) Disassemble one more instruction
seec ( -- ) Continue to see at disasm-$
see name ( -- ) See the definition
Matthias Koch, Summer 2015