Add missing python tools, update README, and more data from James Bowman website about the Gameduino (still looking for the original Sphynx documentation file)
This commit is contained in:
parent
2b0c1e60f3
commit
f622dafc8a
13
README.md
13
README.md
@ -42,6 +42,19 @@ The adapter is controlled via SPI read/write operations, and looks to the CPU li
|
||||
|
||||
[](./doc/poster.pdf)
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
You will find here all the data I've collected about the original Gameduino:
|
||||
- board/ contain the schematic and PCB design for the Gameduino
|
||||
- doc/ Documentation about the Gameduino and j1 CPU
|
||||
- fpga/ The FPGA source for the Gameduino
|
||||
- gd/ The Arduino library for the Gameduino
|
||||
- Python/ A set of tool writen in Python
|
||||
- j1/ The original j1 CPU with it's firmware and FPGA source
|
||||
- j0/ The slightly modified j1 CPU for the Gameduino, as the j0 is part of the Gameduino, only the firmware part is accessible here
|
||||
- archives/ Raw files found on James' website
|
||||
|
||||
Licensing
|
||||
---------
|
||||
|
||||
|
||||
BIN
archives/GameduinoManufacture.zip
Normal file
BIN
archives/GameduinoManufacture.zip
Normal file
Binary file not shown.
BIN
archives/Gameduino_b0.zip
Normal file
BIN
archives/Gameduino_b0.zip
Normal file
Binary file not shown.
BIN
archives/Gameduino_b0m.zip
Normal file
BIN
archives/Gameduino_b0m.zip
Normal file
Binary file not shown.
BIN
archives/Gameduino_b1m.zip
Normal file
BIN
archives/Gameduino_b1m.zip
Normal file
Binary file not shown.
BIN
archives/Gameduino_b2m.zip
Normal file
BIN
archives/Gameduino_b2m.zip
Normal file
Binary file not shown.
BIN
archives/Gameduino_b3m.zip
Normal file
BIN
archives/Gameduino_b3m.zip
Normal file
Binary file not shown.
BIN
archives/Gameduino_m.zip
Normal file
BIN
archives/Gameduino_m.zip
Normal file
Binary file not shown.
6
archives/README.md
Normal file
6
archives/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
Archive Folder
|
||||
==============
|
||||
|
||||
You will find in this folder all the zip files that you can find on James' website related to the Gameduino.
|
||||
|
||||
The files_gameduino.tar.bz2 is an archive of the http://excamera.com/files/gameduino/ folder you can find on James' website
|
||||
BIN
archives/files_gameduino.tar.bz2
Normal file
BIN
archives/files_gameduino.tar.bz2
Normal file
Binary file not shown.
61
j0/firmware/basewords.fs
Normal file
61
j0/firmware/basewords.fs
Normal file
@ -0,0 +1,61 @@
|
||||
( Base words implemented in assembler JCB 13:10 08/24/10)
|
||||
|
||||
meta
|
||||
: noop T alu ;
|
||||
: + T+N d-1 alu ;
|
||||
: xor T^N d-1 alu ;
|
||||
: and T&N d-1 alu ;
|
||||
: or T|N d-1 alu ;
|
||||
: invert ~T alu ;
|
||||
: = N==T d-1 alu ;
|
||||
: < N<T d-1 alu ;
|
||||
: u< Nu<T d-1 alu ;
|
||||
: swap N T->N alu ;
|
||||
: dup T T->N d+1 alu ;
|
||||
: drop N d-1 alu ;
|
||||
: over N T->N d+1 alu ;
|
||||
: nip T d-1 alu ;
|
||||
: >r N T->R r+1 d-1 alu ;
|
||||
: r> rT T->N r-1 d+1 alu ;
|
||||
: r@ rT T->N d+1 alu ;
|
||||
: c@ T alu
|
||||
[T] alu ;
|
||||
: c! T N->[T] d-1 alu
|
||||
N d-1 alu ;
|
||||
: rshift N>>T d-1 alu ;
|
||||
: * N*T d-1 alu ;
|
||||
: swab swabT alu ;
|
||||
: 1- T-1 alu ;
|
||||
: exit return ;
|
||||
|
||||
\ Elided words
|
||||
\ These words are supported by the hardware but are not
|
||||
\ part of ANS Forth. They are named after the word-pair
|
||||
\ that matches their effect The first word is one of
|
||||
\ 2dup, dup or over. Using these elided words instead of
|
||||
\ the pair saves one cycle and one instruction.
|
||||
|
||||
: 2dupand T&N T->N d+1 alu ;
|
||||
: 2dup< N<T T->N d+1 alu ;
|
||||
: 2dup= N==T T->N d+1 alu ;
|
||||
: 2dup* N*T T->N d+1 alu ;
|
||||
: 2dupor T|N T->N d+1 alu ;
|
||||
: 2duprshift N>>T T->N d+1 alu ;
|
||||
: 2dup+ T+N T->N d+1 alu ;
|
||||
: 2dupu< Nu<T T->N d+1 alu ;
|
||||
: 2dupxor T^N T->N d+1 alu ;
|
||||
: dup>r T T->R r+1 alu ;
|
||||
: dupc@ T T->N d+1 alu
|
||||
[T] alu ;
|
||||
: dupswab swabT T->N d+1 alu ;
|
||||
: overand T&N alu ;
|
||||
: over> N<T alu ;
|
||||
: over= N==T alu ;
|
||||
: over* N*T alu ;
|
||||
: overor T|N alu ;
|
||||
: over+ T+N alu ;
|
||||
: overu> Nu<T alu ;
|
||||
: overxor T^N alu ;
|
||||
|
||||
: module[ there [char] " parse preserve ;
|
||||
: ]module s" Compiled " type count type space there swap - . cr ;
|
||||
32
j0/firmware/bgstripes.fs
Normal file
32
j0/firmware/bgstripes.fs
Normal file
@ -0,0 +1,32 @@
|
||||
start-microcode bgstripes
|
||||
|
||||
\ renders a 64-line horizontal stripe in the BG_COLOR
|
||||
\ starting at line COMM+0
|
||||
|
||||
\ Interface:
|
||||
\ COMM+0 stripe start
|
||||
\ 3E80-3EFF 64 color stripe
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: - invert 1+ + ;
|
||||
: 0= d# 0 = ;
|
||||
: @ dup c@ swap 1+ c@ swab or ;
|
||||
: ! over swab over 1+ c! c! ;
|
||||
: 2dup over over ;
|
||||
: min 2dup < ;fallthru
|
||||
: ?: ( xt xf flag -- xt | xf) \ if flag xt, else xf
|
||||
if drop else nip then ;
|
||||
: max 2dup swap < ?: ;
|
||||
|
||||
: main
|
||||
begin
|
||||
YLINE c@ \ line COMM+0 is line zero
|
||||
COMM+0 c@ -
|
||||
d# 0 max d# 63 min \ clamp to 0-63
|
||||
d# 2 * h# 3E80 + \ index into color table
|
||||
@ BG_COLOR ! \ fetch and write
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
|
||||
91
j0/firmware/cold.fs
Normal file
91
j0/firmware/cold.fs
Normal file
@ -0,0 +1,91 @@
|
||||
start-microcode cold
|
||||
|
||||
\ system cold start program
|
||||
|
||||
\ Interface:
|
||||
\ 3400-34FF voices source
|
||||
\ 3800-3FFF palette animation source (64 palettes)
|
||||
|
||||
h# 3400 constant VOICES_COPY
|
||||
h# 3800 constant PALETTES
|
||||
|
||||
d# 32 constant PALSZ \ size of palette in bytes
|
||||
|
||||
: vblank@
|
||||
VBLANK ;fallthru
|
||||
: _c@ c@ ; \ these save 1 instruction per use
|
||||
: _c! c! ;
|
||||
: 1+ d# 1 + ;
|
||||
: @ dup _c@ swap 1+ _c@ swab or ;
|
||||
: up1 ( a -- ) \ subtract 1 from sprite coordinate at a
|
||||
dup>r @ dup h# fe00 and swap 1- h# 1FF and or r> ;fallthru
|
||||
: ! ( u addr )
|
||||
over swab over 1+ _c! _c! ;
|
||||
|
||||
: waitvbi \ wait for start of vertical blanking interval
|
||||
begin vblank@ 1- until
|
||||
begin vblank@ until ;
|
||||
|
||||
: stepfade ( u -- ) \ fade step u is 0-63
|
||||
PALSZ * PALETTES +
|
||||
dup d# 30 + @ BG_COLOR ! \ copy 15th palette entry to BG_COLOR
|
||||
PALETTE16A
|
||||
PALSZ
|
||||
;fallthru
|
||||
: cmove ( src dst n -- )
|
||||
begin
|
||||
dup
|
||||
while
|
||||
>r
|
||||
over _c@ over _c!
|
||||
1+ swap 1+ swap
|
||||
r> 1-
|
||||
repeat
|
||||
drop ;fallthru
|
||||
: 2drop drop drop ;
|
||||
|
||||
: endl ( limit u -- limit u' finished ) \ end of loop
|
||||
waitvbi ;fallthru
|
||||
: qendl \ quick endl, no wait for frame
|
||||
1+
|
||||
2dup=
|
||||
;
|
||||
|
||||
: >VOICES ( a -- ) \ load all voices from a
|
||||
VOICES d# 256 cmove ;
|
||||
|
||||
[ RAM_SPR 2 + ] constant SPR_YS \ sprite Y coordinates
|
||||
|
||||
: main
|
||||
d# 256 d# 0
|
||||
begin
|
||||
dup h# c0 and d# 128 = if
|
||||
dup d# 63 and stepfade
|
||||
then
|
||||
\ copy 3E00+u to VOICES+u
|
||||
dup VOICES_COPY + _c@
|
||||
over VOICES + _c!
|
||||
endl until
|
||||
begin
|
||||
COMM+9 _c@
|
||||
until
|
||||
h# 3500 >VOICES
|
||||
d# 265 d# 0
|
||||
begin
|
||||
d# 256 d# 0
|
||||
begin
|
||||
dup d# 4 * SPR_YS + up1
|
||||
qendl until
|
||||
2drop
|
||||
dup SCROLL_Y !
|
||||
endl until
|
||||
h# 3600 >VOICES
|
||||
d# 0
|
||||
begin
|
||||
waitvbi
|
||||
dup SCROLL_X !
|
||||
1+
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
535
j0/firmware/crossj1.fs
Normal file
535
j0/firmware/crossj1.fs
Normal file
@ -0,0 +1,535 @@
|
||||
( Cross-compiler for the J1 JCB 13:12 08/24/10)
|
||||
decimal
|
||||
|
||||
( outfile is fileid or zero JCB 12:30 11/27/10)
|
||||
|
||||
0 value outfile
|
||||
|
||||
: type ( c-addr u )
|
||||
outfile if
|
||||
outfile write-file throw
|
||||
else
|
||||
type
|
||||
then
|
||||
;
|
||||
: emit ( u )
|
||||
outfile if
|
||||
pad c! pad 1 outfile write-file throw
|
||||
else
|
||||
emit
|
||||
then
|
||||
;
|
||||
: cr ( u )
|
||||
outfile if
|
||||
s" " outfile write-line throw
|
||||
else
|
||||
cr
|
||||
then
|
||||
;
|
||||
: space bl emit ;
|
||||
: spaces dup 0> if 0 do space loop then ;
|
||||
|
||||
vocabulary j1assembler \ assembly storage and instructions
|
||||
vocabulary metacompiler \ the cross-compiling words
|
||||
vocabulary j1target \ actual target words
|
||||
|
||||
: j1asm
|
||||
only
|
||||
metacompiler
|
||||
also j1assembler definitions
|
||||
also forth ;
|
||||
: meta
|
||||
only
|
||||
j1target also
|
||||
j1assembler also
|
||||
metacompiler definitions also
|
||||
forth ;
|
||||
: target
|
||||
only
|
||||
metacompiler also
|
||||
j1target definitions ;
|
||||
|
||||
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
j1asm
|
||||
|
||||
: tcell 2 ;
|
||||
: tcells tcell * ;
|
||||
: tcell+ tcell + ;
|
||||
65536 allocate throw constant tflash
|
||||
|
||||
: h#
|
||||
base @ >r 16 base !
|
||||
0. bl parse >number throw 2drop postpone literal
|
||||
r> base ! ; immediate
|
||||
|
||||
variable tdp
|
||||
: there tdp @ ;
|
||||
: islegal dup h# 7fff u> abort" illegal address" ;
|
||||
: tc! islegal tflash + c! ;
|
||||
: tc@ islegal tflash + c@ ;
|
||||
: t! islegal over h# ff and over tc! swap 8 rshift swap 1+ tc! ;
|
||||
: t@ islegal dup tc@ swap 1+ tc@ 8 lshift or ;
|
||||
: talign tdp @ 1 + h# fffe and tdp ! ;
|
||||
: tc, there tc! 1 tdp +! ;
|
||||
: t, there t! tcell tdp +! ;
|
||||
: org tdp ! ;
|
||||
|
||||
65536 cells allocate throw constant references
|
||||
: referenced cells references + 1 swap +! ;
|
||||
|
||||
65536 cells allocate throw constant labels
|
||||
: atlabel? ( -- f = are we at a label )
|
||||
labels there cells + @ 0<>
|
||||
;
|
||||
|
||||
: coldcross
|
||||
tflash 65536 255 fill
|
||||
labels 65536 cells 0 fill
|
||||
;
|
||||
|
||||
coldcross
|
||||
|
||||
: preserve ( c-addr1 u -- c-addr )
|
||||
dup 1+ allocate throw dup >r
|
||||
2dup c! 1+
|
||||
swap cmove r> ;
|
||||
|
||||
: setlabel ( c-addr u -- )
|
||||
atlabel? if 2drop else preserve labels there cells + ! then ;
|
||||
|
||||
j1asm
|
||||
|
||||
: hex-literal ( u -- c-addr u ) s>d <# bl hold #s [char] $ hold #> ;
|
||||
|
||||
: imm h# 8000 or t, ;
|
||||
|
||||
: T h# 0000 ;
|
||||
: N h# 0100 ;
|
||||
: T+N h# 0200 ;
|
||||
: T&N h# 0300 ;
|
||||
: T|N h# 0400 ;
|
||||
: T^N h# 0500 ;
|
||||
: ~T h# 0600 ;
|
||||
: N==T h# 0700 ;
|
||||
: N<T h# 0800 ;
|
||||
: N>>T h# 0900 ;
|
||||
: T-1 h# 0a00 ;
|
||||
: rT h# 0b00 ;
|
||||
: [T] h# 0c00 ;
|
||||
: N*T h# 0d00 ;
|
||||
: swabT h# 0e00 ;
|
||||
: Nu<T h# 0f00 ;
|
||||
|
||||
: T->N h# 0080 or ;
|
||||
: T->R h# 0040 or ;
|
||||
: N->[T] h# 0020 or ;
|
||||
: d-1 h# 0003 or ;
|
||||
: d+1 h# 0001 or ;
|
||||
: r-1 h# 000c or ;
|
||||
: r-2 h# 0008 or ;
|
||||
: r+1 h# 0004 or ;
|
||||
|
||||
: alu h# 6000 or t, ;
|
||||
|
||||
: return T h# 1000 or r-1 alu ;
|
||||
: ubranch 2/ h# 0000 or t, ;
|
||||
: 0branch 2/ h# 2000 or t, ;
|
||||
: scall 2/ h# 4000 or t, ;
|
||||
|
||||
: dump-words ( c-addr n -- ) \ Write n/2 words from c-addr
|
||||
dup 6 > abort" invalid byte count"
|
||||
2/ dup >r
|
||||
0 do
|
||||
dup t@ s>d <# # # # # #> type space
|
||||
2 +
|
||||
loop drop
|
||||
3 r> - 5 * spaces
|
||||
;
|
||||
|
||||
variable padc
|
||||
: pad+ ( c-addr u -- ) \ append to pad
|
||||
dup >r
|
||||
pad padc @ + swap cmove
|
||||
r> padc +! ;
|
||||
|
||||
: pad+loc ( addr -- )
|
||||
dup cells labels + @ ?dup if
|
||||
nip count pad+
|
||||
else
|
||||
s>d <# #s [char] $ hold #> pad+
|
||||
then
|
||||
s" " pad+
|
||||
;
|
||||
|
||||
|
||||
: disassemble-j
|
||||
0 padc !
|
||||
dup t@ h# 8000 and if
|
||||
s" LIT " pad+
|
||||
dup t@ h# 7fff and hex-literal pad+ exit
|
||||
else
|
||||
dup t@ h# e000 and h# 6000 = if
|
||||
s" ALU " pad+
|
||||
dup t@ pad+loc exit
|
||||
else
|
||||
dup t@ h# e000 and h# 4000 = if
|
||||
s" CALL "
|
||||
else
|
||||
dup t@ h# 2000 and if
|
||||
s" 0BRANCH "
|
||||
else
|
||||
s" BRANCH "
|
||||
then
|
||||
then
|
||||
pad+
|
||||
dup t@ h# 1fff and 2* pad+loc
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
: disassemble-line ( offset -- offset' )
|
||||
dup cells labels + @ ?dup if s" \ " type count type cr then
|
||||
dup s>d <# # # # # #> type space
|
||||
dup 2 dump-words
|
||||
disassemble-j
|
||||
pad padc @ type
|
||||
2 +
|
||||
cr
|
||||
;
|
||||
|
||||
: disassemble-block
|
||||
0 do
|
||||
disassemble-line
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
j1asm
|
||||
|
||||
\ tcompile is like "STATE": it is true when compiling
|
||||
|
||||
variable tcompile
|
||||
: tcompile? tcompile @ ;
|
||||
: +tcompile tcompile? abort" Already in compilation mode" 1 tcompile ! ;
|
||||
: -tcompile 0 tcompile ! ;
|
||||
|
||||
: (literal)
|
||||
\ dup $f rshift over $e rshift xor 1 and throw
|
||||
dup h# 8000 and if
|
||||
h# ffff xor recurse
|
||||
~T alu
|
||||
else
|
||||
h# 8000 or t,
|
||||
then
|
||||
|
||||
;
|
||||
: (t-constant)
|
||||
tcompile? if
|
||||
(literal)
|
||||
then
|
||||
;
|
||||
|
||||
meta
|
||||
|
||||
\ Find name - without consuming it - and return a counted string
|
||||
: wordstr ( "name" -- c-addr u )
|
||||
>in @ >r bl word count r> >in !
|
||||
;
|
||||
|
||||
|
||||
: literal (literal) ; immediate
|
||||
: 2literal swap (literal) (literal) ; immediate
|
||||
: call,
|
||||
dup referenced
|
||||
scall
|
||||
;
|
||||
|
||||
: t:
|
||||
talign
|
||||
wordstr setlabel
|
||||
create
|
||||
there ,
|
||||
+tcompile
|
||||
947947
|
||||
does>
|
||||
@
|
||||
tcompile? if
|
||||
call,
|
||||
then
|
||||
;
|
||||
|
||||
: lookback ( offset -- v ) there swap - t@ ;
|
||||
: prevcall? 2 lookback h# e000 and h# 4000 = ;
|
||||
: call>goto dup t@ h# 1fff and swap t! ;
|
||||
: prevsafe?
|
||||
2 lookback h# e000 and h# 6000 = \ is an ALU
|
||||
2 lookback h# 004c and 0= and ; \ does not touch RStack
|
||||
: alu>return dup t@ h# 1000 or r-1 swap t! ;
|
||||
|
||||
: t; 947947 <> if abort" Unstructured" then
|
||||
true if
|
||||
atlabel? invert prevcall? and if
|
||||
there 2 - call>goto
|
||||
else
|
||||
atlabel? invert prevsafe? and if
|
||||
there 2 - alu>return
|
||||
else
|
||||
return
|
||||
then
|
||||
then
|
||||
else
|
||||
return
|
||||
then
|
||||
-tcompile
|
||||
;
|
||||
|
||||
: t;fallthru 947947 <> if abort" Unstructured" then
|
||||
-tcompile
|
||||
;
|
||||
|
||||
variable shadow-tcompile
|
||||
wordlist constant escape]-wordlist
|
||||
escape]-wordlist set-current
|
||||
: ] shadow-tcompile @ tcompile ! previous previous ;
|
||||
|
||||
meta
|
||||
|
||||
: [
|
||||
tcompile @ shadow-tcompile !
|
||||
-tcompile get-order forth-wordlist escape]-wordlist rot 2 + set-order
|
||||
;
|
||||
|
||||
: : t: ;
|
||||
: ; t; ;
|
||||
: ;fallthru t;fallthru ;
|
||||
: , t, ;
|
||||
: c, tc, ;
|
||||
|
||||
: constant ( n "name" -- ) create , immediate does> @ (t-constant) ;
|
||||
|
||||
: ]asm
|
||||
-tcompile also forth also j1target also j1assembler ;
|
||||
: asm[ +tcompile previous previous previous ;
|
||||
: code t: ]asm ;
|
||||
|
||||
j1asm
|
||||
|
||||
: end-code
|
||||
947947 <> if abort" Unstructured" then
|
||||
previous previous previous ;
|
||||
|
||||
meta
|
||||
|
||||
\ Some Forth words are safe to use in target mode, so import them
|
||||
|
||||
: ( postpone ( ;
|
||||
: \ postpone \ ;
|
||||
|
||||
: import ( "name" -- )
|
||||
>in @ ' swap >in !
|
||||
create , does> @ execute ;
|
||||
|
||||
import meta
|
||||
import org
|
||||
import include
|
||||
import included
|
||||
import marker
|
||||
import [if]
|
||||
import [else]
|
||||
import [then]
|
||||
|
||||
: do-number ( n -- |n )
|
||||
state @ if
|
||||
postpone literal
|
||||
else
|
||||
tcompile? if
|
||||
(literal)
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
decimal
|
||||
|
||||
: [char] ( "name" -- ) ( run: -- ascii) char (literal) ;
|
||||
|
||||
: ['] ( "name" -- ) ( run: -- xt )
|
||||
' tcompile @ >r -tcompile execute r> tcompile !
|
||||
dup referenced
|
||||
(literal)
|
||||
;
|
||||
|
||||
: (sliteral--h) ( addr n -- ptr ) ( run: -- eeaddr n )
|
||||
s" sliteral" evaluate
|
||||
there >r
|
||||
dup tc,
|
||||
0 do count tc, loop
|
||||
drop
|
||||
talign
|
||||
r>
|
||||
;
|
||||
|
||||
: (sliteral) (sliteral--h) drop ;
|
||||
: s" ( "ccc<quote>" -- ) ( run: -- eaddr n ) [char] " parse (sliteral) ;
|
||||
: s' ( "ccc<quote>" -- ) ( run: -- eaddr n ) [char] ' parse (sliteral) ;
|
||||
|
||||
: create
|
||||
wordstr setlabel
|
||||
create there ,
|
||||
does> @ do-number
|
||||
;
|
||||
|
||||
: allot tdp +! ;
|
||||
|
||||
: variable wordstr setlabel create there , 0 t,
|
||||
does> @ do-number ;
|
||||
: 2variable wordstr setlabel create there , 0 t, 0 t,
|
||||
does> @ do-number ;
|
||||
|
||||
: createdoes
|
||||
wordstr setlabel
|
||||
create there , ' ,
|
||||
does> dup @ dup referenced (literal) cell+ @ execute
|
||||
;
|
||||
|
||||
: jumptable
|
||||
wordstr setlabel
|
||||
create there ,
|
||||
does> s" 2*" evaluate @ dup referenced (literal) s" + @" evaluate
|
||||
;
|
||||
|
||||
: | ' execute dup referenced t, ;
|
||||
|
||||
: ', ' execute t, ;
|
||||
|
||||
( DEFER JCB 11:18 11/12/10)
|
||||
|
||||
: defer
|
||||
wordstr setlabel
|
||||
create there , 0 t,
|
||||
does> @ tcompile? if do-number s" @ execute" evaluate then ;
|
||||
|
||||
: is ( xt "name" -- )
|
||||
tcompile? if
|
||||
' >body @ do-number
|
||||
s" ! " evaluate
|
||||
else
|
||||
' execute t!
|
||||
then ;
|
||||
|
||||
: ' ' execute ;
|
||||
|
||||
( VALUE JCB 13:06 11/12/10)
|
||||
|
||||
: value
|
||||
wordstr setlabel
|
||||
create there , t,
|
||||
does> @ do-number s" @" evaluate ;
|
||||
|
||||
: to ( u "name" -- )
|
||||
' >body @ do-number s" !" evaluate ;
|
||||
|
||||
( ARRAY JCB 13:34 11/12/10)
|
||||
|
||||
: array
|
||||
wordstr setlabel
|
||||
create there , 0 do 0 t, loop
|
||||
does> s" cells" evaluate @ do-number s" +" evaluate ;
|
||||
: 2array
|
||||
wordstr setlabel
|
||||
create there , 2* 0 do 0 t, loop
|
||||
does> s" 2* cells" evaluate @ do-number s" +" evaluate ;
|
||||
|
||||
( eforth's way of handling constants JCB 13:12 09/03/10)
|
||||
|
||||
: label: ( "name" -- ) create there , immediate does> @ (t-constant) ;
|
||||
|
||||
: sign>number
|
||||
over c@ [char] - = if
|
||||
1- swap 1+ swap
|
||||
>number
|
||||
2swap dnegate 2swap
|
||||
else
|
||||
>number
|
||||
then
|
||||
;
|
||||
|
||||
: base>number ( caddr u base -- )
|
||||
base @ >r base !
|
||||
sign>number
|
||||
r> base !
|
||||
dup 0= if
|
||||
2drop drop do-number
|
||||
else
|
||||
1 = swap c@ [char] . = and if
|
||||
drop dup do-number 16 rshift do-number
|
||||
else
|
||||
-1 abort" bad number"
|
||||
then
|
||||
then ;
|
||||
|
||||
: d# 0. bl parse 10 base>number ;
|
||||
: h# 0. bl parse 16 base>number ;
|
||||
|
||||
( Conditionals JCB 13:12 09/03/10)
|
||||
: if
|
||||
there
|
||||
0 0branch
|
||||
;
|
||||
|
||||
: resolve
|
||||
dup t@ there 2/ or swap t!
|
||||
;
|
||||
|
||||
: then
|
||||
resolve
|
||||
s" (then)" setlabel
|
||||
;
|
||||
|
||||
: else
|
||||
there
|
||||
0 ubranch
|
||||
swap resolve
|
||||
s" (else)" setlabel
|
||||
;
|
||||
|
||||
|
||||
: begin s" (begin)" setlabel there ;
|
||||
: again
|
||||
ubranch
|
||||
;
|
||||
: until
|
||||
0branch
|
||||
;
|
||||
: while
|
||||
there
|
||||
0 0branch
|
||||
;
|
||||
: repeat
|
||||
swap ubranch
|
||||
resolve
|
||||
s" (repeat)" setlabel
|
||||
;
|
||||
|
||||
: 0do s" >r d# 0 >r" evaluate there s" (do)" setlabel ;
|
||||
: do s" 2>r" evaluate there s" (do)" setlabel ;
|
||||
: loop
|
||||
s" looptest" evaluate 0branch
|
||||
;
|
||||
: i s" r@" evaluate ;
|
||||
|
||||
77 constant sourceline#
|
||||
s" none" 2constant sourcefilename
|
||||
|
||||
: line# sourceline# (literal) ;
|
||||
create currfilename 1 cells 80 + allot
|
||||
variable currfilename#
|
||||
: savestr ( c-addr u dst -- ) 2dup c! 1+ swap cmove ;
|
||||
: getfilename sourcefilename currfilename count compare 0<>
|
||||
if
|
||||
sourcefilename 2dup currfilename savestr (sliteral--h) currfilename# !
|
||||
else
|
||||
currfilename# @ dup 1+ (literal) tc@ (literal)
|
||||
then ;
|
||||
: snap line# getfilename s" (snap)" evaluate ; immediate
|
||||
: assert 0= if line# sourcefilename (sliteral) s" (assert)" evaluate then ; immediate
|
||||
25
j0/firmware/dna.fs
Normal file
25
j0/firmware/dna.fs
Normal file
@ -0,0 +1,25 @@
|
||||
start-microcode dna
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: 2* d# 2 * ;
|
||||
|
||||
: dna@ ( -- u ) h# 8018 c@ ;
|
||||
: dna! ( u -- ) h# 8008 c! ;
|
||||
: dnaclk ( u -- ) dup dna! 1+ dna! ;
|
||||
: dnaread ( ) d# 4 dnaclk ;
|
||||
: dnashift ( ) d# 2 dnaclk ;
|
||||
: dnabit ( u -- u ) 2* dna@ + dnashift ;
|
||||
: dnabyte ( -- u ) \ read byte from DNA
|
||||
d# 0
|
||||
dnabit dnabit dnabit dnabit
|
||||
dnabit dnabit dnabit dnabit ;
|
||||
: main \ write 7 byte DNA to COMM
|
||||
dnaread dnashift
|
||||
COMM+7 COMM+0
|
||||
begin
|
||||
dnabyte over c!
|
||||
1+ 2dup=
|
||||
until
|
||||
begin again ;
|
||||
|
||||
end-microcode
|
||||
729
j0/firmware/eforth.fs
Normal file
729
j0/firmware/eforth.fs
Normal file
@ -0,0 +1,729 @@
|
||||
meta
|
||||
0 value _next
|
||||
variable _lit
|
||||
variable _invert
|
||||
variable _equal
|
||||
variable _plus
|
||||
variable _mul
|
||||
variable _rshift
|
||||
variable _and
|
||||
variable _or
|
||||
variable _xor
|
||||
variable _<
|
||||
variable _u<
|
||||
variable _dup
|
||||
variable _drop
|
||||
variable _swap
|
||||
variable _over
|
||||
variable _c!
|
||||
variable _!
|
||||
variable _c@
|
||||
variable _@
|
||||
variable _>r
|
||||
variable _r>
|
||||
variable _r@
|
||||
variable _branch
|
||||
variable _0branch
|
||||
|
||||
variable _doconst
|
||||
variable _dovar
|
||||
variable _docol
|
||||
variable _semis
|
||||
target
|
||||
|
||||
start-microcode eforth
|
||||
|
||||
\ Interface:
|
||||
\ COMM+0 instruction pointer
|
||||
COMM+0 constant IP
|
||||
: 1+ d# 1 + ;
|
||||
: @ dup c@ swap 1+ c@ swab or ;
|
||||
: IP!
|
||||
IP ;fallthru
|
||||
: ! over swab over 1+ c! c! ;
|
||||
|
||||
: IP@
|
||||
\ COMM+0 c@ COMM+1 c@ swab or ;
|
||||
IP @ ;
|
||||
: fetch \ fetch cell from IP, then increment IP
|
||||
IP@ dup d# 2 + IP! @ ;
|
||||
|
||||
meta there _lit ! target
|
||||
t: _lit
|
||||
drop
|
||||
fetch
|
||||
;fallthru
|
||||
meta there to _next target
|
||||
: _next
|
||||
fetch \ fetch xt
|
||||
dup 1+ swap \ stack the args pointer
|
||||
c@ >r ; \ jump to the code addr
|
||||
|
||||
meta
|
||||
: def there wordstr evaluate ! t: ;
|
||||
: term _next ubranch t;fallthru ;
|
||||
target
|
||||
|
||||
|
||||
def _doconst
|
||||
@ ;fallthru
|
||||
def _dovar
|
||||
term
|
||||
|
||||
def _invert drop invert term
|
||||
def _equal drop = term
|
||||
def _plus drop + term
|
||||
def _mul drop * term
|
||||
def _rshift drop rshift term
|
||||
def _and drop and term
|
||||
def _or drop or term
|
||||
def _xor drop xor term
|
||||
def _< drop < term
|
||||
def _u< drop u< term
|
||||
def _dup drop dup term
|
||||
def _drop drop drop term
|
||||
def _swap drop swap term
|
||||
def _over drop over term
|
||||
def _c! drop c! term
|
||||
def _! drop ! term
|
||||
def _c@ drop c@ term
|
||||
def _@ drop @ term
|
||||
def _>r drop >r term
|
||||
def _r> drop r> term
|
||||
def _r@ drop r@ term
|
||||
def _branch drop fetch IP! term
|
||||
def _0branch drop fetch swap if drop else IP! then term
|
||||
|
||||
\ start a colon definition: push IP and use args as new IP
|
||||
def _docol
|
||||
IP@ >r ;fallthru
|
||||
: IP!term
|
||||
IP! term
|
||||
|
||||
\ end a colon definition: pop IP
|
||||
def _semis
|
||||
drop r> IP!term ;
|
||||
|
||||
[ _next ] constant main
|
||||
|
||||
end-microcode
|
||||
|
||||
meta 0 to outfile
|
||||
|
||||
only forth
|
||||
also metacompiler
|
||||
also forth definitions also
|
||||
|
||||
cr cr cr
|
||||
4000 value dst
|
||||
create dstmem 8000 allot
|
||||
|
||||
s" dump.eforth" w/o create-file throw value dump.eforth
|
||||
|
||||
: dstc@
|
||||
dstmem + c@ ;
|
||||
: dstc!
|
||||
dstmem + c! ;
|
||||
: dst!
|
||||
over 8 rshift over 1+ dstc! dstc! ;
|
||||
: c>>
|
||||
dst dstc!
|
||||
dst 1+ to dst ;
|
||||
: >>
|
||||
dst dst!
|
||||
dst 2 + to dst ;
|
||||
: s>> ( addr u -- )
|
||||
0 do dup c@ c>> 1+ loop drop ;
|
||||
|
||||
0 value 'link
|
||||
|
||||
\ These definitions go into the gdforth wordlist
|
||||
|
||||
vocabulary gdforth
|
||||
|
||||
: gdf-define
|
||||
only
|
||||
gdforth definitions
|
||||
also metacompiler
|
||||
also forth
|
||||
;
|
||||
|
||||
: gdf-use
|
||||
only
|
||||
gdforth definitions
|
||||
;
|
||||
|
||||
gdf-define
|
||||
|
||||
0 value >link
|
||||
: dumpmem
|
||||
\ bring vocab pointer up to date
|
||||
dst 2 - >link .s dst!
|
||||
dstmem 4000 + dst 4000 - dump.eforth write-file throw
|
||||
;
|
||||
|
||||
: meta meta ;
|
||||
|
||||
\ name
|
||||
\ length
|
||||
\ prev
|
||||
\ cfa <--- xt
|
||||
\ args
|
||||
|
||||
: label
|
||||
wordstr tuck s>> c>>
|
||||
'link >> dst to 'link
|
||||
create dst ,
|
||||
does> @ >> ;
|
||||
|
||||
label gdbranch _branch @ c>>
|
||||
label gd0branch _0branch @ c>>
|
||||
|
||||
: begin dst ;
|
||||
: again gdbranch >> ;
|
||||
: until gd0branch >> ;
|
||||
: if gd0branch dst 7777 >> ;
|
||||
: else gdbranch dst >r 8888 >> dst swap dst! r> ;
|
||||
: then dst swap dst! ;
|
||||
: while gd0branch dst 7777 >> ;
|
||||
: repeat swap gdbranch >> dst swap dst! ;
|
||||
|
||||
label (lit) _lit @ c>>
|
||||
label invert _invert @ c>>
|
||||
label = _equal @ c>>
|
||||
label + _plus @ c>>
|
||||
label * _mul @ c>>
|
||||
label rshift _rshift @ c>>
|
||||
label and _and @ c>>
|
||||
label or _or @ c>>
|
||||
label xor _xor @ c>>
|
||||
label < _< @ c>>
|
||||
label u< _u< @ c>>
|
||||
label c! _c! @ c>>
|
||||
label ! _! @ c>>
|
||||
label c@ _c@ @ c>>
|
||||
label @ _@ @ c>>
|
||||
label >r _>r @ c>>
|
||||
label r> _r> @ c>>
|
||||
label r@ _r@ @ c>>
|
||||
label dup _dup @ c>>
|
||||
label drop _drop @ c>>
|
||||
label swap _swap @ c>>
|
||||
label over _over @ c>>
|
||||
label semis _semis @ c>>
|
||||
|
||||
: create label ;
|
||||
: constant label _doconst @ c>> >> ;
|
||||
: variable label _dovar @ c>> 0 >> ;
|
||||
: ivariable label _dovar @ c>> >> ; \ initialized variable
|
||||
: the-link label _dovar @ c>> dst .s to >link 'link >> ; \ variable init to 'link
|
||||
: allot dst +! ;
|
||||
|
||||
: bc-var (lit) _dovar @ >> ;
|
||||
: bc-col (lit) _docol @ >> ;
|
||||
: bc-const (lit) _doconst @ >> ;
|
||||
: bc-var# _dovar @ 0ff and ;
|
||||
: bc-col# _docol @ 0ff and ;
|
||||
: bc-const# _doconst @ 0ff and ;
|
||||
: semis# ['] semis >body @ ;
|
||||
: literal# ['] (lit) >body @ ;
|
||||
: branch# ['] gdbranch >body @ ;
|
||||
: 0branch# ['] gd0branch >body @ ;
|
||||
: '(lit) (lit) (lit) ;
|
||||
|
||||
: \ ['] \ execute ;
|
||||
: ( ['] ( execute ;
|
||||
|
||||
: : label _docol @ c>> ;
|
||||
: ; semis ;
|
||||
: x; semis ; \ alternative name for when ; gets overloaded
|
||||
: immediate
|
||||
'link 3 - dup dstc@ 80 or swap dstc! ;
|
||||
|
||||
: h# (lit) h# >> ;
|
||||
: d# (lit) d# >> ;
|
||||
: [char] (lit) char >> ;
|
||||
|
||||
: fwd4 (lit) dst 4 + >> ;
|
||||
|
||||
gdf-use
|
||||
|
||||
\ constants used for making code
|
||||
semis# constant semis# \ address of the semis word
|
||||
literal# constant literal# \ address of the literal word
|
||||
branch# constant branch# \ address of the branch word
|
||||
0branch# constant 0branch# \ address of the 0branch word
|
||||
|
||||
bc-var# constant bc-var# \ the code byte for _dovar
|
||||
bc-col# constant bc-col# \ the code byte for _docol
|
||||
bc-const# constant bc-const# \ code byte for _doconst
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: 1- d# -1 + ;
|
||||
: <> = invert ;
|
||||
: 2dup over over ;
|
||||
: 0< d# 0 < ;
|
||||
: tuck swap over ;
|
||||
|
||||
20 constant BL
|
||||
0 constant FALSE
|
||||
-1 constant TRUE
|
||||
|
||||
10 ivariable BASE
|
||||
: HEX ( -- )( 6.2.1660 ) D# 16 BASE ! ;
|
||||
: DECIMAL ( -- )( 6.1.1170 ) D# 10 BASE ! ;
|
||||
|
||||
: NIP ( n1 n2 -- n2 )( 6.2.1930 ( 0x4D ) SWAP DROP ;
|
||||
: ROT ( n1 n2 n3 -- n2 n3 n1 )( 6.1.2160 ( 0x4A ) >R SWAP R> SWAP ;
|
||||
: 2DROP ( n n -- )( 6.1.0370 ( 0x52 ) DROP DROP ;
|
||||
: 2DUP ( n1 n2 -- n1 n2 n1 n2 )( 6.1.0380 ( 0x53 ) OVER OVER ;
|
||||
: ?DUP ( n -- n n | 0 )( 6.1.0630 ( 0x50 ) DUP IF DUP THEN ;
|
||||
|
||||
: INVERT ( n -- n )( 6.1.1720 ( 0x26 ) D# -1 XOR ;
|
||||
|
||||
: NEGATE ( n -- n )( 6.1.1910 ( 0x2C ) INVERT D# 1 + ;
|
||||
: - ( n n -- n )( 6.1.0160 ( 0x1F ) NEGATE + ;
|
||||
: ABS ( n -- u )( 6.1.0690 ( 0x2D ) DUP 0< IF NEGATE THEN ;
|
||||
|
||||
: 0= ( n -- f )( 6.1.0270 ( 0x34 ) D# 0 = ;
|
||||
|
||||
: MIN ( n n -- n )( 6.1.1880 ( 0x2E ) 2DUP < IF BEGIN DROP ;
|
||||
: MAX ( n n -- n )( 6.1.1870 ( 0x2F ) 2DUP < UNTIL THEN NIP ;
|
||||
|
||||
: WITHIN ( u ul uh -- f )( 6.2.2440 ( 0x45 ) OVER - >R - R> U< ;
|
||||
|
||||
: 0<> ( n -- f ) d# 0 = invert ;
|
||||
|
||||
: UPPER ( c -- C ) \ convert to uppercase ( upc ( 0x81 ) \ bbb
|
||||
\ DUP [CHAR] a h# 7B WITHIN IF BL XOR THEN ;
|
||||
h# 60 over < if h# 5f and then ;
|
||||
|
||||
\ -----------------------------------------------------------
|
||||
|
||||
2000 constant RAM_PAL
|
||||
0 constant tib
|
||||
variable >in \ offset into TIB
|
||||
variable tibsz \ how much space remains
|
||||
|
||||
2892 constant dp
|
||||
2895 constant BLKRDY
|
||||
2896 constant COUT
|
||||
2897 constant COUTRDY
|
||||
2898 constant CIN
|
||||
|
||||
: ser-emit
|
||||
COUT c!
|
||||
d# 1 COUTRDY c!
|
||||
begin
|
||||
COUTRDY c@ 0=
|
||||
until
|
||||
;
|
||||
|
||||
400 ivariable cursor
|
||||
: vid-emit
|
||||
dup d# 10 = if
|
||||
drop cursor @ h# ffc0 and cursor !
|
||||
else
|
||||
dup d# 13 = if
|
||||
drop cursor @ h# 40 + cursor !
|
||||
else
|
||||
cursor @ tuck c! 1+ cursor !
|
||||
then
|
||||
then
|
||||
;
|
||||
: page
|
||||
d# 4096 d# 0 begin
|
||||
d# 0 over c!
|
||||
1+ 2dup =
|
||||
until 2drop
|
||||
h# 400 cursor !
|
||||
;
|
||||
|
||||
: emit vid-emit ;
|
||||
|
||||
: space bl emit ;
|
||||
: cr d# 13 emit d# 10 emit ;
|
||||
|
||||
: hex1 d# 15 and dup d# 10 < if d# 48 else d# 55 then + emit ;
|
||||
: hex2
|
||||
dup
|
||||
d# 4 rshift
|
||||
hex1 hex1
|
||||
;
|
||||
: hex4
|
||||
dup
|
||||
d# 8 rshift
|
||||
hex2 hex2 ;
|
||||
: hex8 hex4 hex4 ;
|
||||
: . hex4 space ;
|
||||
|
||||
: snap
|
||||
[char] S emit
|
||||
[char] N emit
|
||||
[char] A emit
|
||||
[char] P emit
|
||||
cr
|
||||
hex4 cr
|
||||
hex4 cr
|
||||
hex4 cr
|
||||
hex4 cr
|
||||
hex4 cr
|
||||
hex4 cr
|
||||
hex4 cr
|
||||
hex4 cr
|
||||
begin again
|
||||
;
|
||||
|
||||
: CHAR+ 1+ ;
|
||||
: CHARS ;
|
||||
: PAUSE ;
|
||||
|
||||
: +! ( n a -- )( 6.1.0130 ( 0x6C ) DUP >R @ + R> ! ;
|
||||
: COUNT ( a -- a c )( 6.1.0980 ( 0x84 ) DUP CHAR+ SWAP C@ ;
|
||||
: BOUNDS ( a u -- a+u a )( 0xAC ) OVER + SWAP ;
|
||||
: /STRING ( ca u n -- ca+n u-n )( 17.6.1.0245 ) SWAP OVER - >R CHARS + R> ;
|
||||
: TYPE ( ca u -- )( 6.1.2310 ( 0x90 )
|
||||
PAUSE CHARS BOUNDS BEGIN 2DUP XOR WHILE COUNT EMIT REPEAT 2DROP ;
|
||||
|
||||
: SAME? ( ca ca u -- f )
|
||||
begin
|
||||
dup
|
||||
while
|
||||
>r
|
||||
over c@ upper over c@ upper <> if
|
||||
r> drop 2drop false ;
|
||||
then
|
||||
1+ swap 1+ swap
|
||||
r> 1-
|
||||
repeat
|
||||
drop 2drop true ;
|
||||
|
||||
|
||||
: isimmediate ( xt -- f )
|
||||
d# -3 + c@ h# 80 and 0<> ;
|
||||
: name? ( xt -- ca u )
|
||||
d# -3 + dup c@ h# 7f and tuck - swap ;
|
||||
: sayword ( xt -- )
|
||||
name? type ;
|
||||
|
||||
: inch
|
||||
>in @ tib + ;
|
||||
: inch+1
|
||||
d# 1 >in +! ;
|
||||
|
||||
: execute
|
||||
fwd4 !
|
||||
+ ;
|
||||
|
||||
: advance
|
||||
d# 1 /string d# 1 >in +! ;
|
||||
|
||||
: skipbl ( ca u -- ca u ) \ skip blank chars
|
||||
begin
|
||||
over c@ bl = over 0<> and
|
||||
while
|
||||
advance
|
||||
repeat
|
||||
;
|
||||
|
||||
: skipnbl ( ca u -- ca u ) \ skip nonblank chars
|
||||
begin
|
||||
over c@ bl <> over 0<> and
|
||||
while
|
||||
advance
|
||||
repeat
|
||||
;
|
||||
|
||||
variable source/a
|
||||
variable source/l
|
||||
|
||||
: source ( -- ca u )( 6.1.2216 )
|
||||
source/a @ source/l @ ;
|
||||
: source>in
|
||||
source >in @ /string ;
|
||||
|
||||
: parse-word ( -- ca u )
|
||||
source>in
|
||||
skipbl
|
||||
over >r
|
||||
skipnbl
|
||||
drop
|
||||
r> tuck -
|
||||
;
|
||||
|
||||
|
||||
\ name
|
||||
\ length
|
||||
\ prev
|
||||
\ cfa <--- xt
|
||||
\ args
|
||||
|
||||
: here dp @ ;
|
||||
: c, here c! d# 1 dp +! ;
|
||||
: , here ! d# 2 dp +! ;
|
||||
: s, begin dup while over c@ c, d# 1 /string repeat 2drop ;
|
||||
|
||||
the-link voc
|
||||
0 ivariable state
|
||||
|
||||
: head, ( "name" -- )
|
||||
parse-word
|
||||
tuck s, c,
|
||||
voc @ , here voc !
|
||||
;
|
||||
|
||||
: digit ( c -- u )
|
||||
upper [CHAR] 0 - D# 9 OVER <
|
||||
IF D# 7 - DUP D# 10 < OR THEN ;
|
||||
|
||||
: 1/string d# 1 /string ;
|
||||
|
||||
: isnumber ( ca u -- f )
|
||||
\ over c@ [char] - = if 1/string then
|
||||
true >r
|
||||
begin
|
||||
dup
|
||||
while
|
||||
over c@ digit base @ u< r> and >r
|
||||
1/string
|
||||
repeat
|
||||
2drop r>
|
||||
;
|
||||
|
||||
: asnumber ( ca u -- false | n true )
|
||||
d# 0 >r
|
||||
begin
|
||||
dup
|
||||
while
|
||||
over c@ digit
|
||||
r> base @ * + >r
|
||||
1/string
|
||||
repeat
|
||||
2drop r> true
|
||||
;
|
||||
|
||||
: words
|
||||
voc @
|
||||
begin
|
||||
dup
|
||||
while
|
||||
dup sayword space
|
||||
d# -2 + @
|
||||
repeat
|
||||
cr
|
||||
;
|
||||
|
||||
: sfind ( ca u -- xt | ca u 0 )
|
||||
>r
|
||||
voc @
|
||||
begin
|
||||
dup
|
||||
while
|
||||
2dup name? ( ca xt ca ca u )
|
||||
dup r@ = if
|
||||
SAME? if r> drop nip ; then
|
||||
else
|
||||
2drop drop
|
||||
then
|
||||
d# -2 + @
|
||||
repeat
|
||||
drop r> false
|
||||
;
|
||||
|
||||
variable (quit)
|
||||
|
||||
: interpret
|
||||
begin
|
||||
parse-word
|
||||
dup
|
||||
while
|
||||
sfind ?dup if
|
||||
dup isimmediate state @ 0= or if
|
||||
execute
|
||||
else
|
||||
,
|
||||
then
|
||||
else
|
||||
2dup isnumber if
|
||||
state @ if
|
||||
'(lit) ,
|
||||
asnumber drop
|
||||
,
|
||||
else
|
||||
asnumber drop
|
||||
then
|
||||
else
|
||||
[char] ? emit type (quit) @ execute
|
||||
then
|
||||
then
|
||||
repeat
|
||||
2drop
|
||||
;
|
||||
|
||||
( Gameduino system constants JCB 16:45 04/15/11)
|
||||
|
||||
0000 constant RAM_PIC 1000 constant RAM_CHR
|
||||
2000 constant RAM_PAL 2800 constant IDENT
|
||||
2801 constant REV 2802 constant FRAME
|
||||
2803 constant VBLANK 2804 constant SCROLL_X
|
||||
2806 constant SCROLL_Y 2808 constant JK_MODE
|
||||
280a constant SPR_DISABLE 280b constant SPR_PAGE
|
||||
280c constant IOMODE 280e constant BG_COLOR
|
||||
2810 constant SAMPLE_L 2812 constant SAMPLE_R
|
||||
2a00 constant VOICES 2840 constant PALETTE16A
|
||||
2860 constant PALETTE16B 2880 constant PALETTE4A
|
||||
2888 constant PALETTE4B 2890 constant COMM
|
||||
2900 constant COLLISION 2c00 constant J1_CODE
|
||||
3000 constant RAM_SPR 3800 constant RAM_SPRPAL
|
||||
4000 constant RAM_SPRIMG
|
||||
\ screen \ 11
|
||||
8016 constant FLASH_MISO
|
||||
8018 constant FLASH_MOSI
|
||||
801a constant FLASH_SCK
|
||||
801c constant FLASH_SSEL
|
||||
|
||||
( SPI JCB 16:42 04/15/11)
|
||||
|
||||
: off d# 0 swap c! ; : on d# 1 swap c! ;
|
||||
: spi-sel FLASH_SSEL off ;
|
||||
: spi-unsel FLASH_SSEL on ;
|
||||
: spi-cold spi-unsel FLASH_SCK off ;
|
||||
: spi-1bit ( u -- u ) \ single bit via SPI
|
||||
d# 2 *
|
||||
dup d# 8 rshift FLASH_MOSI c! \ write MSB to MOSI
|
||||
FLASH_SCK on \ raise clock
|
||||
FLASH_MISO c@ or \ read MISO into LSB
|
||||
FLASH_SCK off ; \ drop clock
|
||||
: spi-xfer ( u -- u )
|
||||
spi-1bit spi-1bit spi-1bit spi-1bit
|
||||
spi-1bit spi-1bit spi-1bit spi-1bit ;
|
||||
: >spi spi-xfer drop ;
|
||||
|
||||
( Atmel flash JCB 07:32 04/16/11)
|
||||
|
||||
\ http://www.atmel.com/dyn/resources/prod_documents/doc3638.pdf
|
||||
: flash-status spi-sel h# D7 spi-xfer spi-xfer spi-unsel ;
|
||||
: flash-ready? begin flash-status h# 80 and until ;
|
||||
: flash-page ( u -- ) \ 512*(572+u)
|
||||
d# 572 +
|
||||
dup d# 7 rshift >spi
|
||||
d# 2 * >spi
|
||||
d# 0 >spi ;
|
||||
: page>flash ( a u -- a' u' )
|
||||
spi-sel
|
||||
h# 82 >spi tuck flash-page
|
||||
d# 264 bounds begin
|
||||
dup c@ >spi
|
||||
1+ 2dup =
|
||||
until drop swap 1+ spi-unsel
|
||||
flash-ready? ;
|
||||
: blk>flash ( a u -- )
|
||||
d# 4 * page>flash page>flash page>flash page>flash 2drop ;
|
||||
: flash>page ( u -- )
|
||||
spi-sel
|
||||
h# 03 >spi
|
||||
flash-page
|
||||
h# 0 h# 400 bounds begin
|
||||
d# 0 spi-xfer over c!
|
||||
1+ 2dup =
|
||||
until 2drop spi-unsel ;
|
||||
|
||||
: interpret0
|
||||
d# 0
|
||||
begin
|
||||
>r d# 0 >in !
|
||||
r@ source/a ! d# 64 source/l ! interpret
|
||||
r> h# 40 +
|
||||
dup h# 400 =
|
||||
until drop
|
||||
;
|
||||
|
||||
: load
|
||||
d# 4 * flash>page
|
||||
\ d# 1024 d# 0 begin dup c@ emit 1+ 2dup = until
|
||||
interpret0
|
||||
;
|
||||
|
||||
variable blk
|
||||
|
||||
: key
|
||||
begin CIN c@ ?dup until
|
||||
d# 0 CIN c! ;
|
||||
|
||||
: . hex4 ;
|
||||
|
||||
: quit
|
||||
begin
|
||||
cr
|
||||
begin
|
||||
d# 127 emit d# -1 cursor +!
|
||||
key dup d# 13 xor
|
||||
while
|
||||
emit
|
||||
repeat
|
||||
drop
|
||||
cursor @ h# ffc0 and
|
||||
cursor @ h# 003f and
|
||||
space
|
||||
d# 0 >in !
|
||||
source/l ! source/a ! interpret
|
||||
space
|
||||
[char] o emit
|
||||
[char] k emit
|
||||
again
|
||||
;
|
||||
|
||||
: (
|
||||
source>in
|
||||
begin
|
||||
over c@ [char] ) <>
|
||||
while
|
||||
advance
|
||||
repeat advance 2drop ;
|
||||
|
||||
: nucok
|
||||
[char] N emit
|
||||
[char] U emit
|
||||
[char] C emit
|
||||
space
|
||||
[char] O emit
|
||||
[char] K emit
|
||||
cr ;
|
||||
|
||||
\ : sec
|
||||
\ spi-sel 77 spi-xfer spi-xfer spi-xfer spi-xfer drop
|
||||
\ 80 begin 0 spi-xfer hex2 space next cr ;
|
||||
|
||||
: f;
|
||||
semis# ,
|
||||
d# 0 state ! ; immediate
|
||||
|
||||
: :
|
||||
head,
|
||||
bc-col c,
|
||||
d# 1 state !
|
||||
;
|
||||
|
||||
label main
|
||||
nucok
|
||||
[char] J IOMODE c! spi-cold
|
||||
d# 0 blk !
|
||||
begin
|
||||
begin BLKRDY c@ until
|
||||
|
||||
\ d# 0 blk @ blk>flash d# 1 blk +!
|
||||
|
||||
interpret0
|
||||
d# 0 BLKRDY c!
|
||||
again
|
||||
label blkmain
|
||||
nucok
|
||||
[char] J IOMODE c! spi-cold
|
||||
d# 0 begin
|
||||
dup >r load r> 1+
|
||||
again
|
||||
label stump
|
||||
main
|
||||
|
||||
dumpmem
|
||||
meta
|
||||
22
j0/firmware/eraser.fs
Normal file
22
j0/firmware/eraser.fs
Normal file
@ -0,0 +1,22 @@
|
||||
start-microcode eraser
|
||||
|
||||
COMM+8 constant mask
|
||||
|
||||
: main
|
||||
|
||||
mask c@ >r
|
||||
h# 3FFF h# 7FFF \ RAM_SPRIMG, from top to bottom
|
||||
begin
|
||||
dupc@ r@ and
|
||||
over c!
|
||||
1- 2dup=
|
||||
until
|
||||
|
||||
\ tell host we're done
|
||||
d# 0 COMM+7 c!
|
||||
\ hang
|
||||
begin again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
|
||||
18
j0/firmware/flowtest.fs
Normal file
18
j0/firmware/flowtest.fs
Normal file
@ -0,0 +1,18 @@
|
||||
start-microcode flowtest
|
||||
|
||||
: main
|
||||
begin
|
||||
\ wait until COMM+0 is nonzero
|
||||
begin
|
||||
COMM+0 c@
|
||||
until
|
||||
|
||||
\ increment COMM+1
|
||||
COMM+1 c@ d# 1 + COMM+1 c!
|
||||
|
||||
\ write zero to COMM+0, telling host we're done
|
||||
d# 0 COMM+0 c!
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
22
j0/firmware/helloworld.fs
Normal file
22
j0/firmware/helloworld.fs
Normal file
@ -0,0 +1,22 @@
|
||||
start-microcode helloworld
|
||||
: 1+ d# 1 + ;
|
||||
: writechar ( addr ch -- addr' )
|
||||
over c! 1+ ;
|
||||
|
||||
: main
|
||||
d# 512 \ lines are 64 characters, so this is line 8
|
||||
[char] H writechar
|
||||
[char] E writechar
|
||||
[char] L writechar
|
||||
[char] L writechar
|
||||
[char] O writechar
|
||||
1+
|
||||
[char] W writechar
|
||||
[char] O writechar
|
||||
[char] R writechar
|
||||
[char] L writechar
|
||||
[char] D writechar
|
||||
begin again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
69
j0/firmware/hwdefs.fs
Normal file
69
j0/firmware/hwdefs.fs
Normal file
@ -0,0 +1,69 @@
|
||||
( Hardware register definitions JCB 11:36 01/23/11)
|
||||
|
||||
h# 0000 constant RAM_PIC \ Screen Picture, 64 x 64 = 4096 bytes
|
||||
h# 1000 constant RAM_CHR \ Screen Characters, 256 x 16 = 4096 bytes
|
||||
h# 2000 constant RAM_PAL \ Screen Character Palette, 256 x 8 = 2048 bytes
|
||||
h# 2800 constant IDENT
|
||||
h# 2801 constant REV
|
||||
h# 2802 constant FRAME
|
||||
h# 2803 constant VBLANK
|
||||
h# 2804 constant SCROLL_X
|
||||
h# 2805 constant SCROLL_Xhi
|
||||
h# 2806 constant SCROLL_Y
|
||||
h# 2807 constant SCROLL_Yhi
|
||||
h# 2808 constant JK_MODE
|
||||
h# 2809 constant J1_RESET
|
||||
h# 280a constant SPR_DISABLE
|
||||
h# 280b constant SPR_PAGE
|
||||
h# 280c constant IOMODE
|
||||
h# 280e constant BG_COLOR
|
||||
h# 2810 constant SAMPLE_Llo
|
||||
h# 2811 constant SAMPLE_Lhi
|
||||
h# 2812 constant SAMPLE_Rlo
|
||||
h# 2813 constant SAMPLE_Rhi
|
||||
|
||||
h# 2a00 constant VOICES
|
||||
h# 2840 constant PALETTE16A \ 16-color palette RAM A, 32 bytes
|
||||
h# 2860 constant PALETTE16B \ 16-color palette RAM B, 32 bytes
|
||||
h# 2880 constant PALETTE4A \ 4-color palette RAM A, 8 bytes
|
||||
h# 2888 constant PALETTE4B \ 4-color palette RAM A, 8 bytes
|
||||
h# 2890 constant COMM \ Communication buffer
|
||||
h# 2900 constant COLLISION \ Collision detection RAM, 256 bytes
|
||||
h# 2b00 constant J1_CODE \ J1 coprocessor microcode RAM
|
||||
h# 3000 constant RAM_SPR \ Sprite Control, 512 x 4 = 2048 bytes
|
||||
h# 3800 constant RAM_SPRPAL \ Sprite Palettes, 4 x 256 = 2048 bytes
|
||||
h# 4000 constant RAM_SPRIMG \ Sprite Image, 64 x 256 = 16384 bytes
|
||||
|
||||
[ COMM 0 + ] constant COMM+0
|
||||
[ COMM 1 + ] constant COMM+1
|
||||
[ COMM 2 + ] constant COMM+2
|
||||
[ COMM 3 + ] constant COMM+3
|
||||
[ COMM 4 + ] constant COMM+4
|
||||
[ COMM 5 + ] constant COMM+5
|
||||
[ COMM 6 + ] constant COMM+6
|
||||
[ COMM 7 + ] constant COMM+7
|
||||
[ COMM 8 + ] constant COMM+8
|
||||
[ COMM 9 + ] constant COMM+9
|
||||
[ COMM 10 + ] constant COMM+10
|
||||
[ COMM 11 + ] constant COMM+11
|
||||
[ COMM 12 + ] constant COMM+12
|
||||
[ COMM 13 + ] constant COMM+13
|
||||
[ COMM 14 + ] constant COMM+14
|
||||
[ COMM 15 + ] constant COMM+15
|
||||
|
||||
( Locations for coprocessor only JCB 11:45 02/06/11)
|
||||
|
||||
h# 8000 constant YLINE
|
||||
h# 8002 constant ICAP_O
|
||||
h# 8004 constant ICAP_BUSY
|
||||
h# 8006 constant ICAP_PORT \ see reload.fs for details
|
||||
h# 800a constant FREQHZ
|
||||
h# 800c constant FREQTICK
|
||||
h# 800e constant P2_V
|
||||
h# 8010 constant P2_DIR
|
||||
h# 8012 constant RANDOM
|
||||
h# 8014 constant CLOCK
|
||||
h# 8016 constant FLASH_MISO
|
||||
h# 8018 constant FLASH_MOSI
|
||||
h# 801a constant FLASH_SCK
|
||||
h# 801c constant FLASH_SSEL
|
||||
86
j0/firmware/main.fs
Normal file
86
j0/firmware/main.fs
Normal file
@ -0,0 +1,86 @@
|
||||
include crossj1.fs
|
||||
|
||||
variable filebase
|
||||
|
||||
: suffix ( addr u -- addr u ) \ append suffix to basename
|
||||
0 padc !
|
||||
filebase @ count pad+
|
||||
pad+
|
||||
pad padc @
|
||||
;
|
||||
: create-output-file w/o create-file throw to outfile ;
|
||||
: cbyte s" 0x" type s>d <# # # #> type [char] , emit ;
|
||||
hex
|
||||
variable hiaddr
|
||||
: coderange hiaddr @ 2B00 ;
|
||||
: dumpall \ dump the target memory in every useful format
|
||||
hex
|
||||
|
||||
\ .lst file is a human-readable disassembly
|
||||
s" .lst" suffix create-output-file
|
||||
coderange tuck - 2/ disassemble-block
|
||||
|
||||
\ .binbe is a big-endian binary memory dump
|
||||
s" .binbe" suffix create-output-file
|
||||
coderange do i t@ dup 8 rshift emit emit 2 +loop
|
||||
|
||||
\ .binle is a little-endian binary memory dump
|
||||
s" .binle" suffix create-output-file
|
||||
coderange do i t@ dup emit 8 rshift emit 2 +loop
|
||||
|
||||
\ .h is a little-endian memory dump of bytes 2B00-2BFF
|
||||
s" .h" suffix create-output-file
|
||||
s" static PROGMEM prog_uchar " type
|
||||
filebase @ count type
|
||||
s" _code[] = {" type cr
|
||||
coderange do i t@ dup cbyte 8 rshift cbyte cr 2 +loop
|
||||
s" };" type cr
|
||||
;
|
||||
decimal
|
||||
: start-microcode
|
||||
bl parse preserve filebase !
|
||||
s" marker revert h# 2B02 org" evaluate
|
||||
coldcross decimal
|
||||
;
|
||||
: end-microcode
|
||||
there hiaddr !
|
||||
s" h# 2B00 org code 0jump main ubranch end-code revert meta" evaluate
|
||||
dumpall
|
||||
s" target" evaluate
|
||||
;
|
||||
|
||||
meta
|
||||
coldcross
|
||||
include basewords.fs
|
||||
target
|
||||
include hwdefs.fs
|
||||
|
||||
\ Build all these microcode files:
|
||||
|
||||
include memtest.fs
|
||||
include helloworld.fs
|
||||
include flowtest.fs
|
||||
include setpixel.fs
|
||||
include wireframe.fs
|
||||
include eraser.fs
|
||||
include splitscreen.fs
|
||||
include selftest1.fs
|
||||
include reload.fs
|
||||
include palcopy.fs
|
||||
include random.fs
|
||||
include rasterinterrupt.fs
|
||||
include soundbuffer.fs
|
||||
include cold.fs
|
||||
include testflash.fs
|
||||
include thrasher.fs
|
||||
include bgstripes.fs
|
||||
include dna.fs
|
||||
include regressfreq.fs
|
||||
include showvoices.fs
|
||||
include spectrum.fs
|
||||
include fullscreen_bitmap.fs
|
||||
include videocopy.fs
|
||||
include spr512.fs
|
||||
\ include eforth.fs
|
||||
|
||||
meta
|
||||
54
j0/firmware/memtest.fs
Normal file
54
j0/firmware/memtest.fs
Normal file
@ -0,0 +1,54 @@
|
||||
start-microcode memtest
|
||||
|
||||
32 constant sp
|
||||
0 constant false ( 6.2.1485 )
|
||||
: true ( 6.2.2298 ) d# -1 ;
|
||||
: 1+ d# 1 + ;
|
||||
: rot >r swap r> swap ;
|
||||
: -rot swap >r swap r> ;
|
||||
: 0= d# 0 = ;
|
||||
: tuck swap over ;
|
||||
: 2drop drop drop ;
|
||||
: ?dup dup if dup then ;
|
||||
: 2* d# 2 * ;
|
||||
|
||||
: summit
|
||||
h# 0 c@
|
||||
h# 1 c@ +
|
||||
h# 2 c@ +
|
||||
h# 3 c@ +
|
||||
h# 4 c@ +
|
||||
h# 5 c@ +
|
||||
h# 6 c@ +
|
||||
h# 7 c@ +
|
||||
h# 8 c@ +
|
||||
h# 9 c@ +
|
||||
d# 765
|
||||
\ d# 550
|
||||
over xor
|
||||
if
|
||||
h# DEAD begin again
|
||||
else
|
||||
drop
|
||||
then
|
||||
;
|
||||
|
||||
: move ( c-addr1 c-addr2 u -- )
|
||||
begin
|
||||
>r
|
||||
over noop noop c@ over c!
|
||||
1+ swap 1+ swap
|
||||
r> 1- dup 0=
|
||||
until
|
||||
drop 2drop
|
||||
;
|
||||
|
||||
: main
|
||||
begin
|
||||
h# 0 h# 16 d# 10 move
|
||||
h# 16 h# 0 d# 10 move
|
||||
summit
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
546
j0/firmware/nuc.fs
Normal file
546
j0/firmware/nuc.fs
Normal file
@ -0,0 +1,546 @@
|
||||
( Nucleus: ANS Forth core and ext words JCB 13:11 08/24/10)
|
||||
|
||||
module[ nuc"
|
||||
|
||||
32 constant sp
|
||||
0 constant false ( 6.2.1485 )
|
||||
: depth dsp h# ff and ;
|
||||
: true ( 6.2.2298 ) d# -1 ;
|
||||
: 1+ d# 1 + ;
|
||||
: rot >r swap r> swap ;
|
||||
: -rot swap >r swap r> ;
|
||||
: 0= d# 0 = ;
|
||||
: tuck swap over ;
|
||||
: 2drop drop drop ;
|
||||
: ?dup dup if dup then ;
|
||||
|
||||
: split ( a m -- a&m a&~m )
|
||||
over \ a m a
|
||||
and \ a a&m
|
||||
tuck \ a&m a a&m
|
||||
xor \ a&m a&~m
|
||||
;
|
||||
|
||||
: merge ( a b m -- m?b:a )
|
||||
>r \ a b
|
||||
over xor \ a a^b
|
||||
r> and \ a (a^b)&m
|
||||
xor \ ((a^b)&m)^a
|
||||
;
|
||||
|
||||
: c@ dup @ swap d# 1 and if d# 8 rshift else d# 255 and then ;
|
||||
: c! ( u c-addr )
|
||||
swap h# ff and dup d# 8 lshift or swap
|
||||
tuck dup @ swap ( c-addr u v c-addr )
|
||||
d# 1 and d# 0 = h# ff xor
|
||||
merge swap !
|
||||
;
|
||||
: c!be d# 1 xor c! ;
|
||||
|
||||
: looptest ( -- FIN )
|
||||
r> ( xt )
|
||||
r> ( xt i )
|
||||
1+
|
||||
r@ over = ( xt i FIN )
|
||||
dup if
|
||||
nip r> drop
|
||||
else
|
||||
swap >r
|
||||
then ( xt FIN )
|
||||
swap
|
||||
>r
|
||||
;
|
||||
|
||||
\ Stack
|
||||
: 2dup over over ;
|
||||
: +! tuck @ + swap ! ;
|
||||
|
||||
\ Comparisons
|
||||
: <> = invert ;
|
||||
: 0<> 0= invert ;
|
||||
: 0< d# 0 < ;
|
||||
: 0>= 0< invert ;
|
||||
: 0> d# 0 ;fallthru
|
||||
: > swap < ;
|
||||
: >= < invert ;
|
||||
: <= > invert ;
|
||||
: u> swap u< ;
|
||||
|
||||
\ Arithmetic
|
||||
: negate invert 1+ ;
|
||||
: - negate + ;
|
||||
: abs dup 0< if negate then ;
|
||||
: min 2dup < ;fallthru
|
||||
: ?: ( xt xf f -- xt | xf) if drop else nip then ;
|
||||
: max 2dup > ?: ;
|
||||
code cells end-code
|
||||
code addrcells end-code
|
||||
: 2* d# 1 lshift ;
|
||||
code cell+ end-code
|
||||
code addrcell+ end-code
|
||||
: 2+ d# 2 + ;
|
||||
: 2- 1- 1- ;
|
||||
: 2/ d# 1 rshift ;
|
||||
: c+! tuck c@ + swap c! ;
|
||||
|
||||
: count dup 1+ swap c@ ;
|
||||
: /string dup >r - swap r> + swap ;
|
||||
: aligned 1+ h# fffe and ;
|
||||
|
||||
: sliteral
|
||||
r>
|
||||
count
|
||||
2dup
|
||||
+
|
||||
aligned
|
||||
;fallthru
|
||||
: execute >r ;
|
||||
|
||||
: 15down down1 ;fallthru
|
||||
: 14down down1 ;fallthru
|
||||
: 13down down1 ;fallthru
|
||||
: 12down down1 ;fallthru
|
||||
: 11down down1 ;fallthru
|
||||
: 10down down1 ;fallthru
|
||||
: 9down down1 ;fallthru
|
||||
: 8down down1 ;fallthru
|
||||
: 7down down1 ;fallthru
|
||||
: 6down down1 ;fallthru
|
||||
: 5down down1 ;fallthru
|
||||
: 4down down1 ;fallthru
|
||||
: 3down down1 ;fallthru
|
||||
: 2down down1 ;fallthru
|
||||
: 1down down1 ;fallthru
|
||||
: 0down copy ;
|
||||
|
||||
: 15up up1 ;fallthru
|
||||
: 14up up1 ;fallthru
|
||||
: 13up up1 ;fallthru
|
||||
: 12up up1 ;fallthru
|
||||
: 11up up1 ;fallthru
|
||||
: 10up up1 ;fallthru
|
||||
: 9up up1 ;fallthru
|
||||
: 8up up1 ;fallthru
|
||||
: 7up up1 ;fallthru
|
||||
: 6up up1 ;fallthru
|
||||
: 5up up1 ;fallthru
|
||||
: 4up up1 ;fallthru
|
||||
: 3up up1 ;fallthru
|
||||
: 2up up1 ;fallthru
|
||||
: 1up up1 ;fallthru
|
||||
: 0up ;
|
||||
|
||||
code pickbody
|
||||
copy return
|
||||
1down scall 1up ubranch
|
||||
2down scall 2up ubranch
|
||||
3down scall 3up ubranch
|
||||
4down scall 4up ubranch
|
||||
5down scall 5up ubranch
|
||||
6down scall 6up ubranch
|
||||
7down scall 7up ubranch
|
||||
8down scall 8up ubranch
|
||||
9down scall 9up ubranch
|
||||
10down scall 10up ubranch
|
||||
11down scall 11up ubranch
|
||||
12down scall 12up ubranch
|
||||
13down scall 13up ubranch
|
||||
14down scall 14up ubranch
|
||||
15down scall 15up ubranch
|
||||
end-code
|
||||
|
||||
: pick
|
||||
dup 2* 2* ['] pickbody + execute ;
|
||||
|
||||
: swapdown
|
||||
]asm
|
||||
N T->N alu
|
||||
T d-1 alu
|
||||
asm[
|
||||
;
|
||||
: swapdowns
|
||||
swapdown swapdown swapdown swapdown
|
||||
swapdown swapdown swapdown swapdown
|
||||
swapdown swapdown swapdown swapdown
|
||||
swapdown swapdown swapdown swapdown ;fallthru
|
||||
: swapdown0 ;
|
||||
: roll
|
||||
2*
|
||||
['] 0up over - >r
|
||||
['] swapdown0 swap - execute
|
||||
;
|
||||
|
||||
\ ========================================================================
|
||||
\ Double
|
||||
\ ========================================================================
|
||||
|
||||
: d= ( a b c d -- f )
|
||||
>r \ a b c
|
||||
rot xor \ b a^c
|
||||
swap r> xor \ a^c b^d
|
||||
or 0=
|
||||
;
|
||||
|
||||
: 2@ ( ptr -- lo hi )
|
||||
dup @ swap 2+ @
|
||||
;
|
||||
|
||||
: 2! ( lo hi ptr -- )
|
||||
rot over \ hi ptr lo ptr
|
||||
! 2+ !
|
||||
;
|
||||
|
||||
: 2over >r >r 2dup r> r> ;fallthru
|
||||
: 2swap rot >r rot r> ;
|
||||
: 2nip rot drop rot drop ;
|
||||
: 2rot ( d1 d2 d3 -- d2 d3 d1 ) 2>r 2swap 2r> 2swap ;
|
||||
: 2pick
|
||||
2* 1+ dup 1+ \ lo hi ... 2k+1 2k+2
|
||||
pick \ lo hi ... 2k+1 lo
|
||||
swap \ lo hi ... lo 2k+1
|
||||
pick \ lo hi ... lo hi
|
||||
;
|
||||
|
||||
|
||||
: d+ ( augend . addend . -- sum . )
|
||||
rot + >r ( augend addend)
|
||||
over + ( augend sum)
|
||||
dup rot ( sum sum augend)
|
||||
u< if ( sum)
|
||||
r> 1+
|
||||
else
|
||||
r>
|
||||
then ( sum . )
|
||||
;
|
||||
|
||||
: +h ( u1 u2 -- u1+u2/2**16 )
|
||||
over + ( a a+b )
|
||||
u> d# 1 and
|
||||
;
|
||||
|
||||
: +1c \ one's complement add, as in TCP checksum
|
||||
2dup +h + +
|
||||
;
|
||||
|
||||
: s>d dup 0< ;
|
||||
: d1+ d# 1. d+ ;
|
||||
: dnegate
|
||||
invert swap invert swap
|
||||
d1+
|
||||
;
|
||||
: DABS ( d -- ud ) ( 8.6.1.1160 ) DUP 0< IF DNEGATE THEN ;
|
||||
|
||||
: d- dnegate d+ ;
|
||||
|
||||
\ Write zero to double
|
||||
: dz d# 0 dup rot 2! ;
|
||||
|
||||
: dxor \ ( a b c d -- e f )
|
||||
rot xor \ a c b^d
|
||||
-rot xor \ b^d a^c
|
||||
swap
|
||||
;
|
||||
|
||||
: dand rot and -rot and swap ;
|
||||
: dor rot or -rot or swap ;
|
||||
|
||||
: dinvert invert swap invert swap ;
|
||||
: d< \ ( al ah bl bh -- flag )
|
||||
rot \ al bl bh ah
|
||||
2dup =
|
||||
if
|
||||
2drop u<
|
||||
else
|
||||
2nip >
|
||||
then
|
||||
;
|
||||
|
||||
: d> 2swap d< ;
|
||||
: d0<= d# 0. ;fallthru
|
||||
: d<= d> invert ;
|
||||
: d>= d< invert ;
|
||||
: d0= or 0= ;
|
||||
: d0< d# 0. d< ;
|
||||
: d0<> d0= invert ;
|
||||
: d<> d= invert ;
|
||||
: d2* 2dup d+ ;
|
||||
: d2/ dup d# 15 lshift >r 2/ swap 2/ r> or swap ;
|
||||
: dmax 2over 2over d< if 2swap then 2drop ;
|
||||
|
||||
: d1- d# -1. d+ ;
|
||||
|
||||
: d+! ( v. addr -- )
|
||||
dup >r
|
||||
2@
|
||||
d+
|
||||
r>
|
||||
2!
|
||||
;
|
||||
|
||||
: move ( addr1 addr2 u -- )
|
||||
d# 0 do
|
||||
over @ over !
|
||||
2+ swap 2+ swap
|
||||
loop
|
||||
2drop
|
||||
;
|
||||
|
||||
: cmove ( c-addr1 c-addr2 u -- )
|
||||
d# 0 do
|
||||
over c@ over c!
|
||||
1+ swap 1+ swap
|
||||
loop
|
||||
2drop
|
||||
;
|
||||
|
||||
: bounds ( a n -- a+n a ) OVER + SWAP ;
|
||||
: fill ( c-addr u char -- ) ( 6.1.1540 )
|
||||
>R bounds
|
||||
BEGIN 2dupxor
|
||||
WHILE R@ OVER C! 1+
|
||||
REPEAT R> DROP 2DROP ;
|
||||
|
||||
\ Math
|
||||
|
||||
1 [IF]
|
||||
create scratch d# 2 allot
|
||||
: um* ( u1 u2 -- ud )
|
||||
scratch !
|
||||
d# 0.
|
||||
d# 16 0do
|
||||
2dup d+
|
||||
rot dup 0< if
|
||||
2* -rot
|
||||
scratch @ d# 0 d+
|
||||
else
|
||||
2* -rot
|
||||
then
|
||||
loop
|
||||
rot drop
|
||||
;
|
||||
[ELSE]
|
||||
: um* mult_a ! mult_b ! mult_p 2@ ;
|
||||
[THEN]
|
||||
|
||||
: * um* drop ;
|
||||
: abssgn ( a b -- |a| |b| negf )
|
||||
2dup xor 0< >r abs swap abs swap r> ;
|
||||
|
||||
: m* abssgn >r um* r> if dnegate then ;
|
||||
|
||||
: divstep
|
||||
( divisor dq hi )
|
||||
2*
|
||||
over 0< if 1+ then
|
||||
swap 2* swap
|
||||
rot ( dq hi divisor )
|
||||
2dup >= if
|
||||
tuck ( dq divisor hi divisor )
|
||||
-
|
||||
swap ( dq hi divisor )
|
||||
rot 1+ ( hi divisor dq )
|
||||
rot ( divisor dq hi )
|
||||
else
|
||||
-rot
|
||||
then
|
||||
;
|
||||
|
||||
: um/mod ( ud u1 -- u2 u3 ) ( 6.1.2370 )
|
||||
-rot
|
||||
divstep divstep divstep divstep
|
||||
divstep divstep divstep divstep
|
||||
divstep divstep divstep divstep
|
||||
divstep divstep divstep divstep
|
||||
rot drop swap
|
||||
;
|
||||
|
||||
: /mod >R S>D R> ;fallthru
|
||||
: SM/REM ( d n -- r q ) ( 6.1.2214 ) ( symmetric )
|
||||
OVER >R >R DABS R@ ABS UM/MOD
|
||||
R> R@ XOR 0< IF NEGATE THEN R> 0< IF >R NEGATE R> THEN ;
|
||||
: / /mod nip ;
|
||||
: mod /mod drop ;
|
||||
: */mod >R M* R> SM/REM ;
|
||||
: */ */mod nip ;
|
||||
|
||||
: t2* over >r >r d2*
|
||||
r> 2* r> 0< d# 1 and + ;
|
||||
|
||||
variable divisor
|
||||
: m*/mod
|
||||
divisor !
|
||||
tuck um* 2swap um* ( hi. lo. )
|
||||
( m0 h l m1 )
|
||||
swap >r d# 0 d+ r> ( m h l )
|
||||
-rot ( l m h )
|
||||
d# 32 0do
|
||||
t2*
|
||||
dup divisor @ >= if
|
||||
divisor @ -
|
||||
rot 1+ -rot
|
||||
then
|
||||
loop
|
||||
;
|
||||
: m*/ m*/mod drop ;
|
||||
|
||||
|
||||
\ Numeric output - from eforth
|
||||
|
||||
variable base
|
||||
variable hld
|
||||
create pad 84 allot create pad|
|
||||
|
||||
: <# ( -- ) ( 6.1.0490 )( h# 96 ) pad| HLD ! ;
|
||||
: DIGIT ( u -- c ) d# 9 OVER < d# 7 AND + [CHAR] 0 + ;
|
||||
: HOLD ( c -- ) ( 6.1.1670 ) HLD @ 1- DUP HLD ! C! ;
|
||||
|
||||
: # ( d -- d ) ( 6.1.0030 )
|
||||
d# 0 BASE @ UM/MOD >R BASE @ UM/MOD SWAP DIGIT HOLD R> ;
|
||||
|
||||
: #S ( d -- d ) ( 6.1.0050 ) BEGIN # 2DUP OR 0= UNTIL ;
|
||||
: #> ( d -- a u ) ( 6.1.0040 ) 2DROP HLD @ pad| OVER - ;
|
||||
|
||||
: SIGN ( n -- ) ( 6.1.2210 ) 0< IF [CHAR] - HOLD THEN ;
|
||||
|
||||
\ hex(int((1<<24) * (115200 / 2400.) / (WB_CLOCK_FREQ / 2400.)))
|
||||
\ d# 42000000 constant WB_CLOCK_FREQ
|
||||
|
||||
[ 48000000 17 12 */ ] constant WB_CLOCK_FREQ
|
||||
|
||||
0 [IF]
|
||||
: uartbase
|
||||
[ $100000000. 115200 WB_CLOCK_FREQ m*/ drop $ffffff00 and dup swap 16 rshift ] 2literal
|
||||
;
|
||||
: emit-uart
|
||||
begin uart_0 @ 0= until
|
||||
s>d
|
||||
uartbase dor
|
||||
uart_1 ! uart_0 !
|
||||
;
|
||||
[ELSE]
|
||||
: emit-uart drop ;
|
||||
[THEN]
|
||||
|
||||
create 'emit
|
||||
meta emit-uart t, target
|
||||
|
||||
: emit 'emit @ execute ;
|
||||
: cr d# 13 emit d# 10 emit ;
|
||||
d# 32 constant bl
|
||||
: space bl emit ;
|
||||
: spaces begin dup 0> while space 1- repeat drop ;
|
||||
|
||||
: hex1 d# 15 and dup d# 10 < if d# 48 else d# 55 then + emit ;
|
||||
: hex2
|
||||
dup
|
||||
d# 4 rshift
|
||||
hex1 hex1
|
||||
;
|
||||
: hex4
|
||||
dup
|
||||
d# 8 rshift
|
||||
hex2 hex2 ;
|
||||
|
||||
: hex8 hex4 hex4 ;
|
||||
|
||||
: type
|
||||
d# 0 do
|
||||
dup c@ emit
|
||||
1+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
: dump
|
||||
( addr u )
|
||||
0do
|
||||
dup d# 15 and 0= if dup cr hex4 [char] : emit space space then
|
||||
dup c@ hex2 space 1+
|
||||
loop
|
||||
cr drop
|
||||
;
|
||||
|
||||
: dump16
|
||||
( addr u )
|
||||
0do
|
||||
dup hex4 [char] : emit space dup @ hex4 cr 2+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
: decimal d# 10 base ! ;
|
||||
: hex d# 16 base ! ;
|
||||
|
||||
: S.R ( a u n -- ) OVER - SPACES TYPE ;
|
||||
: D.R ( d n -- ) ( 8.6.1.1070 ) >R DUP >R DABS <# #S R> SIGN #> R> S.R ;
|
||||
: U.R ( u n -- ) ( 6.2.2330 ) d# 0 SWAP D.R ;
|
||||
: .R ( n n -- ) ( 6.2.0210 ) >R S>D R> D.R ;
|
||||
|
||||
: D. ( d -- ) ( 8.6.1.1060 ) d# 0 D.R SPACE ;
|
||||
: U. ( u -- ) ( 6.1.2320 ) d# 0 D. ;
|
||||
: . ( n -- ) ( 6.1.0180 ) BASE @ d# 10 XOR IF U. EXIT THEN S>D D. ;
|
||||
: ? ( a -- ) ( 15.6.1.0600 ) @ . ;
|
||||
|
||||
( Numeric input )
|
||||
|
||||
: DIGIT? ( c base -- u f ) ( 0xA3 )
|
||||
>R [CHAR] 0 - D# 9 OVER <
|
||||
IF D# 7 - DUP D# 10 < OR THEN DUP R> U< ;
|
||||
|
||||
: >number ( ud a u -- ud a u ) ( 6.1.0570 )
|
||||
begin
|
||||
dup 0= if exit then
|
||||
over c@ base @ digit? if
|
||||
>r 2swap
|
||||
drop base @ um*
|
||||
r> s>d d+ 2swap
|
||||
d# 1 /string >number
|
||||
else
|
||||
drop exit
|
||||
then
|
||||
again
|
||||
;
|
||||
|
||||
: .s
|
||||
[char] < emit
|
||||
depth dup hex2
|
||||
[char] > emit
|
||||
|
||||
d# 8 min
|
||||
?dup if
|
||||
0do
|
||||
i pick hex4 space
|
||||
loop
|
||||
then
|
||||
;
|
||||
|
||||
build-debug? [IF]
|
||||
: (assert)
|
||||
s" **** ASSERTION FAILED **** " type
|
||||
;fallthru
|
||||
: (snap)
|
||||
type space
|
||||
s" LINE " type
|
||||
.
|
||||
[char] : emit
|
||||
space
|
||||
.s
|
||||
cr
|
||||
;
|
||||
[THEN]
|
||||
|
||||
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
: endian dup d# 8 lshift swap d# 8 rshift or ;
|
||||
: 2endian endian swap endian ;
|
||||
: swab endian ;
|
||||
: typepad ( c-addr u w ) over - >r type r> spaces ;
|
||||
: even? d# 1 and 0= ;
|
||||
|
||||
\ rise? and fall? act like ! - except that they leave a true
|
||||
\ if the value rose or fell, respectively.
|
||||
|
||||
: rise? ( u a -- f ) 2dup @ u> >r ! r> ;
|
||||
: fall? ( u a -- f ) 2dup @ u< >r ! r> ;
|
||||
|
||||
]module
|
||||
18
j0/firmware/palcopy.fs
Normal file
18
j0/firmware/palcopy.fs
Normal file
@ -0,0 +1,18 @@
|
||||
start-microcode palcopy
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
|
||||
: main
|
||||
\ Copy RAM_PAL to PALETTE16A
|
||||
RAM_PAL PALETTE16A
|
||||
d# 32
|
||||
begin
|
||||
>r
|
||||
over c@ over c!
|
||||
1+ swap 1+ swap
|
||||
r> 1- d# 0 =
|
||||
until
|
||||
begin again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
14
j0/firmware/random.fs
Normal file
14
j0/firmware/random.fs
Normal file
@ -0,0 +1,14 @@
|
||||
start-microcode random
|
||||
|
||||
\ Fill PICTURE and CHARACTER RAM with random numbers
|
||||
|
||||
: main
|
||||
d# 0
|
||||
begin
|
||||
RANDOM c@ over c!
|
||||
1-
|
||||
h# 1FFF and
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
25
j0/firmware/rasterinterrupt.fs
Normal file
25
j0/firmware/rasterinterrupt.fs
Normal file
@ -0,0 +1,25 @@
|
||||
start-microcode rasterinterrupt
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: @ dup c@ swap 1+ c@ swab or ;
|
||||
|
||||
\ COMM+0 holds the 16 bit raster line number:
|
||||
\ 0 is first line of screen
|
||||
\ 299 is last visible line of screen
|
||||
\ 300 is beginning of vertical blanking
|
||||
\
|
||||
\ This microprogram loop raises P2 when the raster is below line COMM+0,
|
||||
\ so the Arduino can trigger an interrupt
|
||||
|
||||
: main
|
||||
d# 0 P2_DIR c! \ Make P2 an output
|
||||
\ Drive P2 high when raster is past line COMM+0
|
||||
begin
|
||||
COMM+0 @ \ user value
|
||||
YLINE c@ \ hardware line
|
||||
< \ true when hardware line is below user value
|
||||
P2_V c! \ write bool to P2
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
19
j0/firmware/regressfreq.fs
Normal file
19
j0/firmware/regressfreq.fs
Normal file
@ -0,0 +1,19 @@
|
||||
start-microcode regressfreq
|
||||
|
||||
\ Reads 16-bit frequency from COMM, generates square
|
||||
\ wave at half frequency PIN2
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: @ dup c@ swap 1+ c@ swab or ;
|
||||
: ! over swab over 1+ c! c! ;
|
||||
|
||||
: main
|
||||
d# 0 P2_DIR c! \ Make P2 an output
|
||||
\ Drive P2 high when raster is past line COMM+0
|
||||
COMM+0 @ FREQHZ c!
|
||||
begin
|
||||
FREQTICK c@ P2_V c!
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
50
j0/firmware/reload.fs
Normal file
50
j0/firmware/reload.fs
Normal file
@ -0,0 +1,50 @@
|
||||
start-microcode reload
|
||||
|
||||
\ This short microprogram forces a full chip reset, just like a power-cycle
|
||||
|
||||
\ it talks to the Spartan 3A's ICAP interface to cause a full FPGA reload,
|
||||
\ as described in
|
||||
\ http://www.xilinx.com/support/documentation/user_guides/ug332.pdf page 278
|
||||
|
||||
\ ICAP data bus is bit-reversed!
|
||||
: rev1 ( a b -- a' b' ) d# 2 * over d# 1 and + swap d# 1 rshift swap ;
|
||||
: rev8 d# 0 rev1 rev1 rev1 rev1 rev1 rev1 rev1 rev1 nip ;
|
||||
|
||||
\ The ICAP_PORT low 8 bits are the reversed ICAP_I byte.
|
||||
\ Bits 8,9,10 are:
|
||||
|
||||
h# 100 constant ICAP-CLK \ 1,0 is a pulse
|
||||
h# 200 constant ICAP-CE \ 0 means select
|
||||
h# 400 constant ICAP-WRITE \ 0 means write
|
||||
|
||||
: ICAP!
|
||||
ICAP_PORT c! ;
|
||||
|
||||
: >cicap ( v -- ) \ clock byte v into ICAP
|
||||
rev8 dup ICAP! ICAP-CLK or ICAP! ;
|
||||
|
||||
: >icap ( v -- ) \ 16-bit ICAP write
|
||||
dup swab >cicap >cicap ;
|
||||
|
||||
: icap_reload
|
||||
h# ffff >icap
|
||||
h# aa99 >icap
|
||||
h# 3261 >icap
|
||||
h# 0000 >icap
|
||||
h# 3281 >icap
|
||||
h# 0000 >icap
|
||||
|
||||
h# 30a1 >icap
|
||||
h# 000e >icap
|
||||
h# 2000 >icap
|
||||
h# 2000 >icap \ needs extra NOOP to complete reboot
|
||||
;
|
||||
|
||||
: main
|
||||
h# 0 ICAP!
|
||||
|
||||
icap_reload
|
||||
begin again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
142
j0/firmware/screens.fs
Normal file
142
j0/firmware/screens.fs
Normal file
@ -0,0 +1,142 @@
|
||||
( 00: JCB 08:33 04/24/11)
|
||||
: immediate voc @ 3 - dup c@ 80 or swap c! f;
|
||||
: ; semis# , 0 state ! f; immediate
|
||||
: exit semis# , ; immediate
|
||||
: \ source nip >in ! ; immediate
|
||||
: allot dp +! ;
|
||||
: create head, bc-var# c, ;
|
||||
: variable head, bc-var# c, 0 , ;
|
||||
: 2variable head, bc-var# c, 0 , 0 , ;
|
||||
: constant head, bc-const# c, , ;
|
||||
: compile, , ;
|
||||
: cell+ 2 + ; : 2* 2 * ; : cells 2* ;
|
||||
|
||||
( 01: branching JCB 08:15 04/24/11)
|
||||
: ahead branch# , here 7777 , ;
|
||||
: 0ahead 0branch# , here 7777 , ;
|
||||
: resolve here swap ! ; \ resolve stacked ref to HERE
|
||||
: begin here ; immediate
|
||||
: again branch# , , ; immediate
|
||||
: until 0branch# , , ; immediate
|
||||
: while 0ahead ; immediate
|
||||
: repeat swap branch# , , resolve ; immediate
|
||||
: if 0ahead ; immediate
|
||||
: else ahead swap resolve ; immediate
|
||||
: then resolve ; immediate
|
||||
|
||||
( 02: parse JCB 08:16 04/24/11)
|
||||
: parse \ ( char -- ca u )
|
||||
source>in
|
||||
advance
|
||||
over >r
|
||||
rot >r
|
||||
begin
|
||||
over c@ r@ <> over 0<> and
|
||||
while
|
||||
advance
|
||||
repeat
|
||||
r> 2drop
|
||||
r> tuck - 1 >in +!
|
||||
;
|
||||
|
||||
( 03: compilation JCB 08:17 04/24/11)
|
||||
: [ 0 state ! ; immediate
|
||||
: ] 1 state ! ;
|
||||
: literal literal# , , ; immediate
|
||||
: char parse-word drop c@ ;
|
||||
: ' parse-word sfind ;
|
||||
: ['] literal# , ' , ; immediate
|
||||
: postpone
|
||||
parse-word sfind
|
||||
dup isimmediate invert if
|
||||
literal# , , ['] ,
|
||||
then , ; immediate
|
||||
: [char] char postpone literal ; immediate
|
||||
: ( [char] ) parse 2drop ; immediate
|
||||
: halt begin again ; ' halt (quit) !
|
||||
|
||||
( 04: debug JCB 08:17 04/24/11)
|
||||
: dump
|
||||
over hex4 bounds
|
||||
begin 2dup xor
|
||||
while space dup c@ hex2 1+
|
||||
repeat 2drop cr ;
|
||||
: isxt voc @ begin 2dup = if 2drop true exit then
|
||||
2 - @ dup 0= until nip ;
|
||||
: typext dup isxt if name? type else hex4 then ;
|
||||
: seelast [char] : emit space voc @ name? type
|
||||
here voc @ 1+ begin
|
||||
2dup xor
|
||||
while space dup @ typext cell+
|
||||
repeat cr 2drop ;
|
||||
|
||||
( 05: strings JCB 08:17 04/24/11)
|
||||
: (sliteral)
|
||||
r> count 2dup + >r ;
|
||||
: s"
|
||||
[char] " parse
|
||||
postpone (sliteral) dup c, s, ; immediate
|
||||
: ." postpone s" postpone type ; immediate
|
||||
: .( [char] ) parse type cr ; immediate
|
||||
: (next) 1- ?dup 0= ;
|
||||
: next postpone (next) postpone until ; immediate
|
||||
|
||||
( 06: move JCB 08:18 04/24/11)
|
||||
: cmove ( c-addr1 c-addr2 u -- )
|
||||
begin
|
||||
dup
|
||||
while
|
||||
>r over c@ over c!
|
||||
1+ swap 1+ swap
|
||||
r> 1-
|
||||
repeat
|
||||
drop 2drop
|
||||
;
|
||||
|
||||
( 07: create does> JCB 08:18 04/24/11)
|
||||
: (create) r> cell+ ;
|
||||
: (does) r> dup cell+ swap @ >r ;
|
||||
: create
|
||||
head, bc-col# c,
|
||||
['] (create) , 0 , ;
|
||||
: does>
|
||||
r> voc @ 1+
|
||||
['] (does) over ! cell+ ! ;
|
||||
: :noname
|
||||
here bc-col# c, ] ;
|
||||
|
||||
( 08: welcome JCB 08:18 04/24/11)
|
||||
\ screen \ 8
|
||||
.( gdforth 0.0.1)
|
||||
here hex4 cr
|
||||
' quit (quit) !
|
||||
|
||||
( 09: DNA JCB 08:19 04/24/11)
|
||||
: dna@ ( -- u ) 8018 c@ ;
|
||||
: dna! ( u -- ) 8008 c! ;
|
||||
: dnaclk ( u -- ) dup dna! 1+ dna! ;
|
||||
: dnaread ( ) 4 dnaclk ;
|
||||
: dnashift ( ) 2 dnaclk ;
|
||||
: dnabit ( u -- u ) 2* dna@ + dnashift ;
|
||||
: dnabyte ( -- u ) \ read byte from DNA
|
||||
0 8 begin >r dnabit r> next ;
|
||||
: dna ( ca -- ) \ write 7 byte DNA at ca
|
||||
dnaread dnashift
|
||||
7 begin
|
||||
>r dnabyte over c! 1+ r>
|
||||
next drop ;
|
||||
\ 7F00 dna 7F00 7 dump
|
||||
( 10: SPI and flash JCB 08:19 04/24/11)
|
||||
char J IOMODE c! spi-cold
|
||||
\ flash-status hex2 cr
|
||||
: showblk ( u -- )
|
||||
spi-sel
|
||||
03 >spi
|
||||
flash-page
|
||||
400 400 bounds begin
|
||||
0 spi-xfer over c!
|
||||
1+ 2dup =
|
||||
until 2drop spi-unsel ;
|
||||
\ 0 showblk
|
||||
\ here hex4 cr
|
||||
quit
|
||||
24
j0/firmware/selftest1.fs
Normal file
24
j0/firmware/selftest1.fs
Normal file
@ -0,0 +1,24 @@
|
||||
start-microcode selftest1
|
||||
: 1+ d# 1 + ;
|
||||
: ! ( u addr )
|
||||
over swab over 1+ c! c! ;
|
||||
: d1+
|
||||
swap 1+
|
||||
swap over
|
||||
d# 0 = if
|
||||
1+
|
||||
then
|
||||
;
|
||||
|
||||
\ increment COMM+0,1,2,3 until COMM+15 goes high
|
||||
: main
|
||||
h# 0.
|
||||
begin
|
||||
over COMM+0 !
|
||||
dup COMM+2 !
|
||||
d1+
|
||||
begin COMM+15 c@ until
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
31
j0/firmware/setpixel.fs
Normal file
31
j0/firmware/setpixel.fs
Normal file
@ -0,0 +1,31 @@
|
||||
start-microcode setpixel
|
||||
|
||||
: setpixel ( yx -- ) \ set pixel yx to color from COMM+2, about 35 cycles
|
||||
dup>r
|
||||
h# f and
|
||||
r@ d# 4 rshift h# 0ff0 and or
|
||||
r@ h# 30 and swab or
|
||||
RAM_SPRIMG or ( addr )
|
||||
dupc@ ( addr v )
|
||||
h# c0 r> d# 5 rshift h# 6 and rshift dup>r \ mask in R
|
||||
invert and r> COMM+2 c@ and or
|
||||
swap c!
|
||||
;
|
||||
|
||||
: main
|
||||
begin
|
||||
\ wait until command reg is nonzero
|
||||
begin
|
||||
COMM+2 c@
|
||||
until
|
||||
|
||||
\ 0 is X, 1 is Y
|
||||
COMM+0 c@ COMM+1 c@ swab or
|
||||
setpixel
|
||||
|
||||
\ tell host we're done
|
||||
d# 0 COMM+2 c!
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
17
j0/firmware/showvoices.fs
Normal file
17
j0/firmware/showvoices.fs
Normal file
@ -0,0 +1,17 @@
|
||||
start-microcode showvoices
|
||||
|
||||
\ continuously move sprites 0-63 to match amplitude of the
|
||||
\ 64 sound voices.
|
||||
|
||||
: main
|
||||
d# 0
|
||||
begin
|
||||
dup d# 4 * VOICES + d# 2 + c@ \ read voice amplitude
|
||||
invert
|
||||
over d# 4 * RAM_SPR + d# 2 + c! \ write as sprite Y coord
|
||||
1- h# 3f and \ next voice
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
|
||||
33
j0/firmware/soundbuffer.fs
Normal file
33
j0/firmware/soundbuffer.fs
Normal file
@ -0,0 +1,33 @@
|
||||
start-microcode soundbuffer
|
||||
|
||||
\ Interface:
|
||||
\ COMM+0 sound read pointer
|
||||
\ 3F00-3FFF sound buffer
|
||||
|
||||
\ This microprogram provides a simple sound sample buffer.
|
||||
\ It reads 8-bit samples from the buffer at 3F00-3FFF and
|
||||
\ writes them to the audio sample registers SAMPLE_L and
|
||||
\ SAMPLE_R.
|
||||
\ The current buffer read pointer is COMM+0.
|
||||
|
||||
h# 3f00 constant BUFFER
|
||||
[ 125 50 * ] constant CYCLE \ one cycle of 8KHz in clocks
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: - invert 1+ + ;
|
||||
|
||||
: main
|
||||
d# 0 ( when )
|
||||
begin
|
||||
CLOCK c@ over - \ positive means CLOCK has passed `when`
|
||||
d# 0 < invert if
|
||||
COMM+0 c@ dup
|
||||
h# 3f00 + c@
|
||||
dup SAMPLE_Lhi c! SAMPLE_Rhi c!
|
||||
1+ COMM+0 c!
|
||||
CYCLE +
|
||||
then
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
99
j0/firmware/spectrum.fs
Normal file
99
j0/firmware/spectrum.fs
Normal file
@ -0,0 +1,99 @@
|
||||
start-microcode spectrum
|
||||
|
||||
\ Interface:
|
||||
\ 4000-57FF Spectrum bitmap
|
||||
\ 5800-5AFF Spectrum attributes
|
||||
\ 7000 attribute lookup: 256 bytes. 64 colors of (paper, ink)
|
||||
\ 7100 pixel stretch, 16 bytes.
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: 0= d# 0 = ;
|
||||
: 4* d# 4 * ;
|
||||
: 64mod h# 3f and ;
|
||||
|
||||
: copy1 ( src dst -- src' dst' ) \ copy one byte
|
||||
over c@
|
||||
over c!
|
||||
1+
|
||||
;fallthru
|
||||
: n1+ ( a b -- a+1 b )
|
||||
swap 1+ swap ;
|
||||
|
||||
\ copy attrs for line y
|
||||
\ dst is RAM_PAL or RAM_PAL+256
|
||||
|
||||
: attrcopy ( y -- )
|
||||
dup 4* h# 5800 + swap ( src y )
|
||||
h# 8 and d# 32 * RAM_PAL + ( src dst )
|
||||
begin
|
||||
over c@ 64mod 4* h# 7000 + swap \ fetch and lookup attribute
|
||||
copy1 copy1 d# 4 + copy1 copy1 nip
|
||||
n1+
|
||||
dup h# ff and 0=
|
||||
until
|
||||
drop drop
|
||||
;
|
||||
|
||||
: stretch! ( dst a -- dst' ) \ expand 4 bit graphic a, write to dst
|
||||
h# f and
|
||||
h# 7100 + c@
|
||||
over c! 1+
|
||||
;
|
||||
|
||||
: byte ( src dst -- src' dst' )
|
||||
over c@ swap ( src a dst )
|
||||
|
||||
over d# 4 rshift stretch!
|
||||
swap stretch! ( src dst' )
|
||||
swap h# 100 + swap \ down 1 line in spectrum video memory
|
||||
;
|
||||
|
||||
: byte4
|
||||
byte byte byte byte ;
|
||||
|
||||
: pixelcopy ( y -- y )
|
||||
dup 64mod 4* h# 4000 +
|
||||
over h# c0 and d# 32 * + ( y src )
|
||||
begin
|
||||
dup
|
||||
dup 64mod d# 16 * RAM_CHR +
|
||||
byte4 byte4
|
||||
drop drop
|
||||
1+
|
||||
dup h# 1f and 0=
|
||||
until drop
|
||||
;
|
||||
|
||||
\ Spectrum memory layout is a bit twisted
|
||||
\ line 0 4000, 4001, 4002
|
||||
\ 1 4100, 4101
|
||||
\ ...
|
||||
\ 8 4020
|
||||
\ ...
|
||||
\ 56 40e0, ... 40ff
|
||||
\ ...
|
||||
\ 63 47e0 47ff
|
||||
\ 64 4800
|
||||
\ 65 4900
|
||||
\ ...
|
||||
\ 191 57e0
|
||||
|
||||
\ at line 0 can start work on 4020
|
||||
\ at line 8 can start work on 4040
|
||||
\ at line 16 can start work on 4060
|
||||
\ 56 4800
|
||||
\
|
||||
\ So in general, at line Y can start work on converting from:
|
||||
\ 4000 + (((Y+8) & 38) * 4) + (((y+8) & c0) * 32)
|
||||
|
||||
: main
|
||||
d# 0
|
||||
begin
|
||||
begin dup d# 48 + YLINE c@ = until
|
||||
d# 8 + h# ff and
|
||||
dup attrcopy
|
||||
pixelcopy
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
29
j0/firmware/splitscreen.fs
Normal file
29
j0/firmware/splitscreen.fs
Normal file
@ -0,0 +1,29 @@
|
||||
start-microcode splitscreen
|
||||
|
||||
: 1+ d# 1 + ;
|
||||
: @ dupc@ swap 1+ c@ swab or ;
|
||||
|
||||
: waitline ( u -- ) \ wait until raster is past u
|
||||
begin
|
||||
dup YLINE c@ =
|
||||
until
|
||||
drop
|
||||
;
|
||||
|
||||
: loadscroll ( a -- ) \ load SCROLL_X,Y from a
|
||||
dup c@ SCROLL_X c! 1+
|
||||
dup c@ SCROLL_Xhi c! 1+
|
||||
dup c@ SCROLL_Y c! 1+
|
||||
c@ dup SCROLL_Yhi c!
|
||||
d# 7 rshift SPR_DISABLE c!
|
||||
;
|
||||
|
||||
: main
|
||||
begin
|
||||
COMM+4 @ waitline COMM+6 loadscroll
|
||||
COMM+10 @ waitline COMM+12 loadscroll
|
||||
d# 300 waitline COMM+0 loadscroll
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
13
j0/firmware/spr512.fs
Normal file
13
j0/firmware/spr512.fs
Normal file
@ -0,0 +1,13 @@
|
||||
start-microcode spr512
|
||||
|
||||
: main
|
||||
begin
|
||||
d# 150
|
||||
YLINE c@
|
||||
<
|
||||
SPR_PAGE c!
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
|
||||
42
j0/firmware/testflash.fs
Normal file
42
j0/firmware/testflash.fs
Normal file
@ -0,0 +1,42 @@
|
||||
start-microcode testflash
|
||||
|
||||
: off d# 0 swap c! ;
|
||||
: on d# 1 swap c! ;
|
||||
|
||||
: spi-sel FLASH_SSEL off ;
|
||||
: spi-unsel FLASH_SSEL on ;
|
||||
: spi-cold spi-unsel FLASH_SCK off ;
|
||||
|
||||
: spi-1bit ( u -- u ) \ single bit via SPI
|
||||
d# 2 *
|
||||
dup swab FLASH_MOSI c! \ write MSB to MOSI
|
||||
FLASH_SCK on \ raise clock
|
||||
FLASH_MISO c@ or \ read MISO into LSB
|
||||
FLASH_SCK off ; \ drop clock
|
||||
|
||||
: spi-xfer ( u -- u )
|
||||
spi-1bit
|
||||
spi-1bit
|
||||
spi-1bit
|
||||
spi-1bit
|
||||
spi-1bit
|
||||
spi-1bit
|
||||
spi-1bit
|
||||
spi-1bit ;
|
||||
|
||||
\ See Atmel AT45DB021D datasheet:
|
||||
\ http://www.atmel.com/dyn/resources/prod_documents/doc3638.pdf
|
||||
|
||||
: main
|
||||
spi-cold
|
||||
spi-sel
|
||||
h# d7 spi-xfer \ flash read status command
|
||||
spi-xfer \ send junk, receive status
|
||||
spi-unsel
|
||||
|
||||
COMM+0 c! \ write status to COMM+0
|
||||
|
||||
begin again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
69
j0/firmware/wireframe.fs
Normal file
69
j0/firmware/wireframe.fs
Normal file
@ -0,0 +1,69 @@
|
||||
start-microcode wireframe
|
||||
|
||||
\ See http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
||||
|
||||
COMM+0 constant X0
|
||||
COMM+1 constant Y0
|
||||
COMM+2 constant X1
|
||||
COMM+3 constant Y1
|
||||
COMM+4 constant steep
|
||||
COMM+5 constant deltax
|
||||
COMM+6 constant deltay
|
||||
COMM+7 constant ystep
|
||||
COMM+8 constant color
|
||||
|
||||
: setpixel ( yx -- ) \ set pixel yx to color
|
||||
dup>r
|
||||
h# f and
|
||||
r@ d# 4 rshift h# 0ff0 and or
|
||||
r@ h# 30 and swab or
|
||||
RAM_SPRIMG or ( addr )
|
||||
dupc@ ( addr v )
|
||||
color c@ r> d# 5 rshift h# 6 and rshift or
|
||||
swap c!
|
||||
;
|
||||
|
||||
: negate invert ;fallthru
|
||||
: 1+ d# 1 + ;
|
||||
: @ dupc@ swap 1+ c@ swab or ;
|
||||
: byte h# ff and ;
|
||||
|
||||
: bresenham
|
||||
deltay c@ negate >r \ keep -deltay on R stack for speed
|
||||
X0 @ \ load y0x0
|
||||
deltax c@ d# 1 rshift \ load deltax/1, is error
|
||||
|
||||
( y0x0 error )
|
||||
begin
|
||||
over byte X1 c@ xor
|
||||
while
|
||||
over
|
||||
steep c@ if swab then
|
||||
setpixel
|
||||
r@ + \ error -= deltay
|
||||
dup d# 0 < if
|
||||
deltax c@ + \ error += deltax
|
||||
ystep c@ swab 1+
|
||||
else
|
||||
d# 1
|
||||
then
|
||||
>r swap r> + swap \ increment YX
|
||||
repeat
|
||||
r> drop
|
||||
;
|
||||
|
||||
: main
|
||||
begin
|
||||
\ wait until command reg is nonzero
|
||||
begin
|
||||
ystep c@
|
||||
until
|
||||
|
||||
bresenham
|
||||
|
||||
\ tell host we're done
|
||||
d# 0 ystep c!
|
||||
again
|
||||
;
|
||||
|
||||
end-microcode
|
||||
29
j1/firmware/Makefile
Normal file
29
j1/firmware/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
j1.mem j1.bin: *.fs Makefile
|
||||
@echo ': version s" '`svnversion`'" ;' > version.fs
|
||||
date
|
||||
@date +': builddate d# %s. d# %z ;' >> version.fs
|
||||
@gforth -e 'include main.fs bye'
|
||||
|
||||
doc: *.fs Makefile
|
||||
gforth -e 'include ../../docforth/docforth.fs s" document.fs" document bye'
|
||||
mkdir -p html
|
||||
mv *.html html
|
||||
|
||||
# PRGDIR=$(HOME)/wge100_firmware/trunk/synth/programming_files/latest
|
||||
PRGDIR=../hardware/synth/programming_files/latest
|
||||
|
||||
wge100_ip_camera.bit: $(PRGDIR)/wge100.bit j1.mem $(PRGDIR)/wge100_bd.bmm
|
||||
(. /opt/Xilinx/11.1/ISE/settings32.sh ; data2mem -bm $(PRGDIR)/wge100_bd.bmm -bd j1.mem tag jram -bt $(PRGDIR)/wge100.bit -o b wge100_ip_camera.bit )
|
||||
|
||||
wge100_ip_camera.mcs: wge100_ip_camera.bit
|
||||
(. /opt/Xilinx/11.1/ISE/settings32.sh ; linux32 promgen -w -p mcs -c FF -o wge100_ip_camera.mcs -u 0 wge100_ip_camera.bit >/dev/null )
|
||||
|
||||
defines_tcpip.fs defines_tcpip2.fs: genoffsets.py defines*py
|
||||
python genoffsets.py
|
||||
|
||||
download: j1.mem
|
||||
./send
|
||||
sudo python listenterminal.py
|
||||
|
||||
bundle: j1.bin wge100_ip_camera.mcs
|
||||
cp j1.bin wge100_ip_camera.mcs tools/*.py $(HOME)/bundle
|
||||
46
j1/firmware/ans.fs
Normal file
46
j1/firmware/ans.fs
Normal file
@ -0,0 +1,46 @@
|
||||
( Main file for pure ANS forth JCB 13:53 11/27/10)
|
||||
|
||||
: parse-word
|
||||
bl word count ;
|
||||
|
||||
: defer create ( "name" -- )
|
||||
['] abort , does> @ execute ;
|
||||
|
||||
: include ( "filename" -- )
|
||||
bl word count included decimal ;
|
||||
|
||||
: is ( xt "name" -- )
|
||||
' ( xt xt2)
|
||||
state @ if
|
||||
postpone literal postpone >body postpone !
|
||||
else
|
||||
>body !
|
||||
then ; immediate
|
||||
|
||||
|
||||
: include ( "filename" -- )
|
||||
bl parse included decimal ;
|
||||
|
||||
: Do-Vocabulary ( -- )
|
||||
DOES> @ >R ( )( R: widnew)
|
||||
GET-ORDER SWAP DROP ( wid_n ... wid_2 n)
|
||||
R> SWAP SET-ORDER ;
|
||||
|
||||
: VOCABULARY ( "name" -- )
|
||||
WORDLIST CREATE , Do-Vocabulary ;
|
||||
|
||||
: -rot rot rot ;
|
||||
: nstime 0. ;
|
||||
: <= > invert ;
|
||||
: >= < invert ;
|
||||
: d0<> d0= invert ;
|
||||
|
||||
: f> fswap f< ;
|
||||
: f<= f> invert ;
|
||||
: f>= f< invert ;
|
||||
: f= 0e0 f~ ;
|
||||
: f<> f= invert ;
|
||||
|
||||
3.1415926e0 fconstant pi
|
||||
|
||||
include main.fs
|
||||
225
j1/firmware/arp.fs
Normal file
225
j1/firmware/arp.fs
Normal file
@ -0,0 +1,225 @@
|
||||
( ARP: Address Resolution Protocol JCB 13:12 08/24/10)
|
||||
module[ arp"
|
||||
|
||||
\ ARP uses a small cache of entries. Each entry has an age counter; new
|
||||
\ entries have an age of 0, any entry with an age >N is old.
|
||||
\
|
||||
|
||||
|
||||
d# 12 constant arp-cache-entry-size
|
||||
d# 5 constant arp-cache-entries
|
||||
TARGET? [IF]
|
||||
meta
|
||||
arp-cache-entry-size arp-cache-entries * d# 64 max
|
||||
target
|
||||
constant arp-size
|
||||
create arp-cache arp-size allot
|
||||
meta
|
||||
arp-cache-entries 1- arp-cache-entry-size * arp-cache +
|
||||
target
|
||||
constant arp-cache-last
|
||||
[ELSE]
|
||||
arp-cache-entry-size arp-cache-entries * d# 64 max constant arp-size
|
||||
create arp-cache arp-size allot
|
||||
arp-cache-entries 1- arp-cache-entry-size * arp-cache + constant arp-cache-last
|
||||
[THEN]
|
||||
|
||||
: arp-foreach \ (func -- )
|
||||
arp-cache-last 2>r
|
||||
begin
|
||||
2r@ swap \ ptr func
|
||||
execute
|
||||
r> dup arp-cache-entry-size - >r
|
||||
arp-cache =
|
||||
until
|
||||
2r> 2drop
|
||||
;
|
||||
|
||||
build-debug? [IF]
|
||||
: arp-.
|
||||
dup @ hex4 space \ age
|
||||
dup 2+ dup @ swap d# 2 + dup @ swap d# 2 + @ ethaddr-pretty space
|
||||
d# 8 + 2@ ip-pretty
|
||||
cr
|
||||
;
|
||||
|
||||
: arp-dump
|
||||
['] arp-. arp-foreach
|
||||
;
|
||||
[THEN]
|
||||
|
||||
: arp-del h# ff swap ! ;
|
||||
: arp-reset ['] arp-del arp-foreach ;
|
||||
: used? @ h# ff <> ;
|
||||
: arp-age-1 dup used? d# 1 and swap +! ;
|
||||
: arp-age ['] arp-age-1 arp-foreach ;
|
||||
: arp-cmp ( ptr0 ptr1 -- ptr) over @ over @ > ?: ;
|
||||
: arp-oldest \ return the address of the oldest ARP entry
|
||||
arp-cache ['] arp-cmp arp-foreach ;
|
||||
|
||||
\ ARP offsets
|
||||
\ d# 28 sender ethaddr
|
||||
\ d# 34 sender ip
|
||||
\ d# 38 target ethaddr
|
||||
\ d# 44 target ip
|
||||
|
||||
d# 20 constant OFFSET_ARP_OPCODE
|
||||
d# 22 constant OFFSET_ARP_SRC_ETH
|
||||
d# 28 constant OFFSET_ARP_SRC_IP
|
||||
d# 32 constant OFFSET_ARP_DST_ETH
|
||||
d# 38 constant OFFSET_ARP_DST_IP
|
||||
|
||||
: arp-is-response
|
||||
OFFSET_ETH_TYPE packet@ h# 806 =
|
||||
OFFSET_ARP_OPCODE packet@ d# 2 =
|
||||
and
|
||||
;
|
||||
|
||||
\ write the current arp response into the cache, replacing the oldest entry
|
||||
: !-- \ ( val ptr -- ptr-2 )
|
||||
tuck \ ptr val ptr
|
||||
!
|
||||
2-
|
||||
;
|
||||
|
||||
\ Current packet is an ARP response; write it to the given slot in the ARP cache, ageing all others
|
||||
|
||||
: arp-cache-write \ ( ptr -- )
|
||||
arp-age \ because this new entry will have age d# 0
|
||||
d# 0 over ! \ age d# 0
|
||||
>r
|
||||
|
||||
d# 3 OFFSET_ARP_SRC_ETH mac-inoffset mac@n
|
||||
r@ d# 6 + !-- !-- !-- drop
|
||||
d# 2 OFFSET_ARP_SRC_IP mac-inoffset mac@n
|
||||
r> d# 8 + 2!
|
||||
|
||||
;
|
||||
|
||||
\ Comparison of IP
|
||||
: arp-cmpip \ (ip01 ip23 ptr/0 ptr -- ip01 ip23 ptr)
|
||||
dup used? if
|
||||
dup d# 8 + 2@ d# 2 2pick d<> ?:
|
||||
else
|
||||
drop
|
||||
then
|
||||
;
|
||||
|
||||
: arp-cache-find ( ip01 ip23 -- ip01 ip23 ptr )
|
||||
\ Find an IP. Zero if the IP was not found in the cache, ptr to entry otherwise
|
||||
d# 0 ['] arp-cmpip arp-foreach ;
|
||||
|
||||
|
||||
: arp-issue-whohas \ (ip01 ip23 -- ptr)
|
||||
mac-pkt-begin
|
||||
ethaddr-broadcast mac-pkt-3,
|
||||
net-my-mac mac-pkt-3,
|
||||
h# 806 \ frame type
|
||||
d# 1 \ hard type
|
||||
h# 800 \ prot type
|
||||
mac-pkt-3,
|
||||
h# 0604 \ hard size, prot size
|
||||
d# 1 \ op (1=request)
|
||||
mac-pkt-2,
|
||||
net-my-mac mac-pkt-3,
|
||||
net-my-ip mac-pkt-2,
|
||||
ethaddr-broadcast mac-pkt-3,
|
||||
mac-pkt-2,
|
||||
mac-pkt-complete drop
|
||||
mac-send
|
||||
;
|
||||
|
||||
\ Look up ethaddr for given IP.
|
||||
\ If found, return pointer to the 6-byte ethaddr
|
||||
\ If not found, issue an ARP request and return d# 0.
|
||||
|
||||
: arp-lookup \ ( ip01 ip23 -- ptr)
|
||||
2dup
|
||||
ip-router 2@ dxor ip-subnetmask 2@ dand
|
||||
d0<>
|
||||
if
|
||||
2drop
|
||||
ip-router 2@
|
||||
then
|
||||
arp-cache-find \ ip01 ip23 ptr
|
||||
dup 0= if
|
||||
-rot \ d# 0 ip01 ip23
|
||||
arp-issue-whohas \ d# 0
|
||||
else
|
||||
nip nip 2+ \ ptr
|
||||
then
|
||||
;
|
||||
|
||||
\ If the current packet is an ARP request for our IP, answer it
|
||||
: arp-responder
|
||||
\ is destination ff:ff:ff:ff:ff:ff or my mac
|
||||
d# 3 OFFSET_ETH_DST mac-inoffset mac@n
|
||||
and and invert 0=
|
||||
|
||||
net-my-mac \ a b c
|
||||
d# 2 OFFSET_ETH_DST 2+ mac-inoffset mac@n
|
||||
d= swap \ F a
|
||||
OFFSET_ETH_DST packet@ = and
|
||||
|
||||
or
|
||||
OFFSET_ETH_TYPE packet@ h# 806 = and
|
||||
\ is target IP mine?
|
||||
d# 2 OFFSET_ARP_DST_IP mac-inoffset mac@n net-my-ip d= and
|
||||
if
|
||||
mac-pkt-begin
|
||||
|
||||
d# 3 OFFSET_ARP_SRC_ETH mac-pkt-src
|
||||
net-my-mac mac-pkt-3,
|
||||
h# 806 \ frame type
|
||||
d# 1 \ hard type
|
||||
h# 800 \ prot type
|
||||
mac-pkt-3,
|
||||
h# 0604 \ hard size, prot size
|
||||
d# 2 \ op (2=reply)
|
||||
mac-pkt-2,
|
||||
net-my-mac mac-pkt-3,
|
||||
net-my-ip mac-pkt-2,
|
||||
d# 3 OFFSET_ARP_SRC_ETH mac-pkt-src
|
||||
d# 2 OFFSET_ARP_SRC_IP mac-pkt-src
|
||||
|
||||
mac-pkt-complete drop
|
||||
mac-send
|
||||
then
|
||||
;
|
||||
|
||||
: arp-announce
|
||||
mac-pkt-begin
|
||||
|
||||
ethaddr-broadcast mac-pkt-3,
|
||||
net-my-mac mac-pkt-3,
|
||||
h# 806 \ frame type
|
||||
d# 1 \ hard type
|
||||
h# 800 \ prot type
|
||||
mac-pkt-3,
|
||||
h# 0604 \ hard size, prot size
|
||||
d# 2 \ op (2=reply)
|
||||
mac-pkt-2,
|
||||
net-my-mac mac-pkt-3,
|
||||
net-my-ip mac-pkt-2,
|
||||
ethaddr-broadcast mac-pkt-3,
|
||||
net-my-ip mac-pkt-2,
|
||||
|
||||
mac-pkt-complete drop
|
||||
mac-send
|
||||
|
||||
;
|
||||
|
||||
: arp-handler
|
||||
arp-responder
|
||||
arp-is-response
|
||||
if
|
||||
d# 2 OFFSET_ARP_SRC_IP mac-inoffset mac@n
|
||||
arp-cache-find nip nip
|
||||
dup 0= if
|
||||
drop arp-oldest
|
||||
then
|
||||
arp-cache-write
|
||||
then
|
||||
;
|
||||
|
||||
]module
|
||||
60
j1/firmware/basewords.fs
Normal file
60
j1/firmware/basewords.fs
Normal file
@ -0,0 +1,60 @@
|
||||
( Base words implemented in assembler JCB 13:10 08/24/10)
|
||||
|
||||
meta
|
||||
: noop T alu ;
|
||||
: + T+N d-1 alu ;
|
||||
: xor T^N d-1 alu ;
|
||||
: and T&N d-1 alu ;
|
||||
: or T|N d-1 alu ;
|
||||
: invert ~T alu ;
|
||||
: = N==T d-1 alu ;
|
||||
: < N<T d-1 alu ;
|
||||
: u< Nu<T d-1 alu ;
|
||||
: swap N T->N alu ;
|
||||
: dup T T->N d+1 alu ;
|
||||
: drop N d-1 alu ;
|
||||
: over N T->N d+1 alu ;
|
||||
: nip T d-1 alu ;
|
||||
: >r N T->R r+1 d-1 alu ;
|
||||
: r> rT T->N r-1 d+1 alu ;
|
||||
: r@ rT T->N d+1 alu ;
|
||||
: @ [T] alu ;
|
||||
: ! T N->[T] d-1 alu
|
||||
N d-1 alu ;
|
||||
: dsp dsp T->N d+1 alu ;
|
||||
: lshift N<<T d-1 alu ;
|
||||
: rshift N>>T d-1 alu ;
|
||||
: 1- T-1 alu ;
|
||||
: 2r> rT T->N r-1 d+1 alu
|
||||
rT T->N r-1 d+1 alu
|
||||
N T->N alu ;
|
||||
: 2>r N T->N alu
|
||||
N T->R r+1 d-1 alu
|
||||
N T->R r+1 d-1 alu ;
|
||||
: 2r@ rT T->N r-1 d+1 alu
|
||||
rT T->N r-1 d+1 alu
|
||||
N T->N d+1 alu
|
||||
N T->N d+1 alu
|
||||
N T->R r+1 d-1 alu
|
||||
N T->R r+1 d-1 alu
|
||||
N T->N alu ;
|
||||
: unloop
|
||||
T r-1 alu
|
||||
T r-1 alu ;
|
||||
: exit return ;
|
||||
|
||||
\ Elided words
|
||||
: dup@ [T] T->N d+1 alu ;
|
||||
: dup>r T T->R r+1 alu ;
|
||||
: 2dupxor T^N T->N d+1 alu ;
|
||||
: 2dup= N==T T->N d+1 alu ;
|
||||
: !nip T N->[T] d-1 alu ;
|
||||
: 2dup! T N->[T] alu ;
|
||||
|
||||
\ Words used to implement pick
|
||||
: up1 T d+1 alu ;
|
||||
: down1 T d-1 alu ;
|
||||
: copy N alu ;
|
||||
|
||||
: module[ there [char] " parse preserve ;
|
||||
: ]module s" Compiled " type count type space there swap - . cr ;
|
||||
90
j1/firmware/clock.fs
Normal file
90
j1/firmware/clock.fs
Normal file
@ -0,0 +1,90 @@
|
||||
( Clock JCB 10:54 11/17/10)
|
||||
|
||||
variable seconds
|
||||
variable minutes
|
||||
variable hours
|
||||
variable days
|
||||
variable months
|
||||
variable years
|
||||
variable weekday
|
||||
|
||||
: show2 ( a -- ) @ s>d <# # # #> type ;
|
||||
|
||||
: setdate ( ud -- )
|
||||
[ -8 3600 * ] literal s>d d+
|
||||
d# 1 d# 60 m*/mod seconds !
|
||||
d# 1 d# 60 m*/mod minutes !
|
||||
d# 1 d# 24 m*/mod hours !
|
||||
d# 59. d- \ Days since Mar 1 1900
|
||||
2dup d# 1 d# 7 m*/mod weekday ! 2drop
|
||||
d# 365 um/mod ( days years )
|
||||
dup d# 1900 + years !
|
||||
d# 4 / 1- - \ subtract leaps ( daynum 0-365 )
|
||||
dup d# 5 * d# 308 + d# 153 / d# 2 - months !
|
||||
months @ d# 4 + d# 153 d# 5 */ - d# 122 + days !
|
||||
|
||||
home
|
||||
'emit @ >r
|
||||
['] vga-bigemit 'emit !
|
||||
|
||||
s" ThuFriSatSunMonTueWed" drop
|
||||
weekday @ d# 3 * + d# 3 type cr
|
||||
s" MarAprMayJunJulAugSepOctNovDecJanFeb" drop
|
||||
months @ d# 3 * + d# 3 type
|
||||
space days @ d# 0 .r cr
|
||||
years @ . cr
|
||||
|
||||
true if
|
||||
hours show2
|
||||
minutes show2
|
||||
seconds show2
|
||||
home
|
||||
then
|
||||
|
||||
r> 'emit !
|
||||
;
|
||||
|
||||
: setdelay ( ud -- )
|
||||
'emit @ >r
|
||||
['] vga-emit 'emit !
|
||||
d# 32 d# 0 vga-at-xy
|
||||
s" ntp " type <# # # # [char] . hold #s #> type
|
||||
s" ms " type
|
||||
r> 'emit !
|
||||
;
|
||||
|
||||
include ntp.fs
|
||||
|
||||
2variable ntp-alarm
|
||||
|
||||
: clock-main
|
||||
vga-page
|
||||
d# 1000000. ntp-alarm setalarm
|
||||
begin
|
||||
begin
|
||||
mac-fullness
|
||||
while
|
||||
arp-handler
|
||||
OFFSET_ETH_TYPE packet@ h# 800 =
|
||||
if
|
||||
d# 2 OFFSET_IP_DSTIP mac-inoffset mac@n net-my-ip d=
|
||||
if
|
||||
icmp-handler
|
||||
then
|
||||
loader-handler
|
||||
ntp-handler
|
||||
then
|
||||
|
||||
depth if .s cr then
|
||||
mac-consume
|
||||
repeat
|
||||
|
||||
ntp-alarm isalarm if
|
||||
ntp-request
|
||||
d# 1000000. ntp-alarm setalarm
|
||||
then
|
||||
|
||||
next?
|
||||
until
|
||||
;
|
||||
|
||||
527
j1/firmware/crossj1.fs
Normal file
527
j1/firmware/crossj1.fs
Normal file
@ -0,0 +1,527 @@
|
||||
( Cross-compiler for the J1 JCB 13:12 08/24/10)
|
||||
decimal
|
||||
|
||||
( outfile is fileid or zero JCB 12:30 11/27/10)
|
||||
|
||||
0 value outfile
|
||||
|
||||
: type ( c-addr u )
|
||||
outfile if
|
||||
outfile write-file throw
|
||||
else
|
||||
type
|
||||
then
|
||||
;
|
||||
: emit ( u )
|
||||
outfile if
|
||||
pad c! pad 1 outfile write-file throw
|
||||
else
|
||||
emit
|
||||
then
|
||||
;
|
||||
: cr ( u )
|
||||
outfile if
|
||||
s" " outfile write-line throw
|
||||
else
|
||||
cr
|
||||
then
|
||||
;
|
||||
: space bl emit ;
|
||||
: spaces dup 0> if 0 do space loop then ;
|
||||
|
||||
vocabulary j1assembler \ assembly storage and instructions
|
||||
vocabulary metacompiler \ the cross-compiling words
|
||||
vocabulary j1target \ actual target words
|
||||
|
||||
: j1asm
|
||||
only
|
||||
metacompiler
|
||||
also j1assembler definitions
|
||||
also forth ;
|
||||
: meta
|
||||
only
|
||||
j1target also
|
||||
j1assembler also
|
||||
metacompiler definitions also
|
||||
forth ;
|
||||
: target
|
||||
only
|
||||
metacompiler also
|
||||
j1target definitions ;
|
||||
|
||||
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
j1asm
|
||||
|
||||
: tcell 2 ;
|
||||
: tcells tcell * ;
|
||||
: tcell+ tcell + ;
|
||||
65536 allocate throw constant tflash
|
||||
|
||||
: h#
|
||||
base @ >r 16 base !
|
||||
0. bl parse >number throw 2drop postpone literal
|
||||
r> base ! ; immediate
|
||||
|
||||
variable tdp
|
||||
: there tdp @ ;
|
||||
: islegal dup h# 7fff u> abort" illegal address" ;
|
||||
: tc! islegal tflash + c! ;
|
||||
: tc@ islegal tflash + c@ ;
|
||||
: t! islegal over h# ff and over tc! swap 8 rshift swap 1+ tc! ;
|
||||
: t@ islegal dup tc@ swap 1+ tc@ 8 lshift or ;
|
||||
: talign tdp @ 1 + h# fffe and tdp ! ;
|
||||
: tc, there tc! 1 tdp +! ;
|
||||
: t, there t! tcell tdp +! ;
|
||||
: org tdp ! ;
|
||||
|
||||
tflash 65536 255 fill
|
||||
|
||||
65536 cells allocate throw constant references
|
||||
: referenced cells references + 1 swap +! ;
|
||||
|
||||
65536 cells allocate throw constant labels
|
||||
labels 65536 cells 0 fill
|
||||
: atlabel? ( -- f = are we at a label )
|
||||
labels there cells + @ 0<>
|
||||
;
|
||||
|
||||
: preserve ( c-addr1 u -- c-addr )
|
||||
dup 1+ allocate throw dup >r
|
||||
2dup c! 1+
|
||||
swap cmove r> ;
|
||||
|
||||
: setlabel ( c-addr u -- )
|
||||
atlabel? if 2drop else preserve labels there cells + ! then ;
|
||||
|
||||
j1asm
|
||||
|
||||
: hex-literal ( u -- c-addr u ) s>d <# bl hold #s [char] $ hold #> ;
|
||||
|
||||
: imm h# 8000 or t, ;
|
||||
|
||||
: T h# 0000 ;
|
||||
: N h# 0100 ;
|
||||
: T+N h# 0200 ;
|
||||
: T&N h# 0300 ;
|
||||
: T|N h# 0400 ;
|
||||
: T^N h# 0500 ;
|
||||
: ~T h# 0600 ;
|
||||
: N==T h# 0700 ;
|
||||
: N<T h# 0800 ;
|
||||
: N>>T h# 0900 ;
|
||||
: T-1 h# 0a00 ;
|
||||
: rT h# 0b00 ;
|
||||
: [T] h# 0c00 ;
|
||||
: N<<T h# 0d00 ;
|
||||
: dsp h# 0e00 ;
|
||||
: Nu<T h# 0f00 ;
|
||||
|
||||
: T->N h# 0080 or ;
|
||||
: T->R h# 0040 or ;
|
||||
: N->[T] h# 0020 or ;
|
||||
: d-1 h# 0003 or ;
|
||||
: d+1 h# 0001 or ;
|
||||
: r-1 h# 000c or ;
|
||||
: r-2 h# 0008 or ;
|
||||
: r+1 h# 0004 or ;
|
||||
|
||||
: alu h# 6000 or t, ;
|
||||
|
||||
: return T h# 1000 or r-1 alu ;
|
||||
: ubranch 2/ h# 0000 or t, ;
|
||||
: 0branch 2/ h# 2000 or t, ;
|
||||
: scall 2/ h# 4000 or t, ;
|
||||
|
||||
: dump-words ( c-addr n -- ) \ Write n/2 words from c-addr
|
||||
dup 6 > abort" invalid byte count"
|
||||
2/ dup >r
|
||||
0 do
|
||||
dup t@ s>d <# # # # # #> type space
|
||||
2 +
|
||||
loop drop
|
||||
3 r> - 5 * spaces
|
||||
;
|
||||
|
||||
variable padc
|
||||
: pad+ ( c-addr u -- ) \ append to pad
|
||||
dup >r
|
||||
pad padc @ + swap cmove
|
||||
r> padc +! ;
|
||||
|
||||
: pad+loc ( addr -- )
|
||||
dup cells labels + @ ?dup if
|
||||
nip count pad+
|
||||
else
|
||||
s>d <# #s [char] $ hold #> pad+
|
||||
then
|
||||
s" " pad+
|
||||
;
|
||||
|
||||
|
||||
: disassemble-j
|
||||
0 padc !
|
||||
dup t@ h# 8000 and if
|
||||
s" LIT " pad+
|
||||
dup t@ h# 7fff and hex-literal pad+ exit
|
||||
else
|
||||
dup t@ h# e000 and h# 6000 = if
|
||||
s" ALU " pad+
|
||||
dup t@ pad+loc exit
|
||||
else
|
||||
dup t@ h# e000 and h# 4000 = if
|
||||
s" CALL "
|
||||
else
|
||||
dup t@ h# 2000 and if
|
||||
s" 0BRANCH "
|
||||
else
|
||||
s" BRANCH "
|
||||
then
|
||||
then
|
||||
pad+
|
||||
dup t@ h# 1fff and 2* pad+loc
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
: disassemble-line ( offset -- offset' )
|
||||
dup cells labels + @ ?dup if s" \ " type count type cr then
|
||||
dup s>d <# # # # # #> type space
|
||||
dup 2 dump-words
|
||||
disassemble-j
|
||||
pad padc @ type
|
||||
2 +
|
||||
cr
|
||||
;
|
||||
|
||||
: disassemble-block
|
||||
0 do
|
||||
disassemble-line
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
j1asm
|
||||
|
||||
\ tcompile is like "STATE": it is true when compiling
|
||||
|
||||
variable tcompile
|
||||
: tcompile? tcompile @ ;
|
||||
: +tcompile tcompile? abort" Already in compilation mode" 1 tcompile ! ;
|
||||
: -tcompile 0 tcompile ! ;
|
||||
|
||||
: (literal)
|
||||
\ dup $f rshift over $e rshift xor 1 and throw
|
||||
dup h# 8000 and if
|
||||
h# ffff xor recurse
|
||||
~T alu
|
||||
else
|
||||
h# 8000 or t,
|
||||
then
|
||||
|
||||
;
|
||||
: (t-constant)
|
||||
tcompile? if
|
||||
(literal)
|
||||
then
|
||||
;
|
||||
|
||||
meta
|
||||
|
||||
\ Find name - without consuming it - and return a counted string
|
||||
: wordstr ( "name" -- c-addr u )
|
||||
>in @ >r bl word count r> >in !
|
||||
;
|
||||
|
||||
|
||||
: literal (literal) ; immediate
|
||||
: 2literal swap (literal) (literal) ; immediate
|
||||
: call,
|
||||
dup referenced
|
||||
scall
|
||||
;
|
||||
|
||||
: t:
|
||||
talign
|
||||
wordstr setlabel
|
||||
create
|
||||
there ,
|
||||
+tcompile
|
||||
947947
|
||||
does>
|
||||
@
|
||||
tcompile? if
|
||||
call,
|
||||
then
|
||||
;
|
||||
|
||||
: lookback ( offset -- v ) there swap - t@ ;
|
||||
: prevcall? 2 lookback h# e000 and h# 4000 = ;
|
||||
: call>goto dup t@ h# 1fff and swap t! ;
|
||||
: prevsafe?
|
||||
2 lookback h# e000 and h# 6000 = \ is an ALU
|
||||
2 lookback h# 004c and 0= and ; \ does not touch RStack
|
||||
: alu>return dup t@ h# 1000 or r-1 swap t! ;
|
||||
|
||||
: t; 947947 <> if abort" Unstructured" then
|
||||
true if
|
||||
atlabel? invert prevcall? and if
|
||||
there 2 - call>goto
|
||||
else
|
||||
atlabel? invert prevsafe? and if
|
||||
there 2 - alu>return
|
||||
else
|
||||
return
|
||||
then
|
||||
then
|
||||
else
|
||||
return
|
||||
then
|
||||
-tcompile
|
||||
;
|
||||
|
||||
: t;fallthru 947947 <> if abort" Unstructured" then
|
||||
-tcompile
|
||||
;
|
||||
|
||||
variable shadow-tcompile
|
||||
wordlist constant escape]-wordlist
|
||||
escape]-wordlist set-current
|
||||
: ] shadow-tcompile @ tcompile ! previous previous ;
|
||||
|
||||
meta
|
||||
|
||||
: [
|
||||
tcompile @ shadow-tcompile !
|
||||
-tcompile get-order forth-wordlist escape]-wordlist rot 2 + set-order
|
||||
;
|
||||
|
||||
: : t: ;
|
||||
: ; t; ;
|
||||
: ;fallthru t;fallthru ;
|
||||
: , t, ;
|
||||
: c, tc, ;
|
||||
|
||||
: constant ( n "name" -- ) create , immediate does> @ (t-constant) ;
|
||||
|
||||
: ]asm
|
||||
-tcompile also forth also j1target also j1assembler ;
|
||||
: asm[ +tcompile previous previous previous ;
|
||||
: code t: ]asm ;
|
||||
|
||||
j1asm
|
||||
|
||||
: end-code
|
||||
947947 <> if abort" Unstructured" then
|
||||
previous previous previous ;
|
||||
|
||||
meta
|
||||
|
||||
\ Some Forth words are safe to use in target mode, so import them
|
||||
|
||||
: ( postpone ( ;
|
||||
: \ postpone \ ;
|
||||
|
||||
: import ( "name" -- )
|
||||
>in @ ' swap >in !
|
||||
create , does> @ execute ;
|
||||
|
||||
import meta
|
||||
import org
|
||||
import include
|
||||
import [if]
|
||||
import [else]
|
||||
import [then]
|
||||
|
||||
: do-number ( n -- |n )
|
||||
state @ if
|
||||
postpone literal
|
||||
else
|
||||
tcompile? if
|
||||
(literal)
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
decimal
|
||||
|
||||
: [char] ( "name" -- ) ( run: -- ascii) char (literal) ;
|
||||
|
||||
: ['] ( "name" -- ) ( run: -- xt )
|
||||
' tcompile @ >r -tcompile execute r> tcompile !
|
||||
dup referenced
|
||||
(literal)
|
||||
;
|
||||
|
||||
: (sliteral--h) ( addr n -- ptr ) ( run: -- eeaddr n )
|
||||
s" sliteral" evaluate
|
||||
there >r
|
||||
dup tc,
|
||||
0 do count tc, loop
|
||||
drop
|
||||
talign
|
||||
r>
|
||||
;
|
||||
|
||||
: (sliteral) (sliteral--h) drop ;
|
||||
: s" ( "ccc<quote>" -- ) ( run: -- eaddr n ) [char] " parse (sliteral) ;
|
||||
: s' ( "ccc<quote>" -- ) ( run: -- eaddr n ) [char] ' parse (sliteral) ;
|
||||
|
||||
: create
|
||||
wordstr setlabel
|
||||
create there ,
|
||||
does> @ do-number
|
||||
;
|
||||
|
||||
: allot tdp +! ;
|
||||
|
||||
: variable wordstr setlabel create there , 0 t,
|
||||
does> @ do-number ;
|
||||
: 2variable wordstr setlabel create there , 0 t, 0 t,
|
||||
does> @ do-number ;
|
||||
|
||||
: createdoes
|
||||
wordstr setlabel
|
||||
create there , ' ,
|
||||
does> dup @ dup referenced (literal) cell+ @ execute
|
||||
;
|
||||
|
||||
: jumptable
|
||||
wordstr setlabel
|
||||
create there ,
|
||||
does> s" 2*" evaluate @ dup referenced (literal) s" + @" evaluate
|
||||
;
|
||||
|
||||
: | ' execute dup referenced t, ;
|
||||
|
||||
: ', ' execute t, ;
|
||||
|
||||
( DEFER JCB 11:18 11/12/10)
|
||||
|
||||
: defer
|
||||
wordstr setlabel
|
||||
create there , 0 t,
|
||||
does> @ tcompile? if do-number s" @ execute" evaluate then ;
|
||||
|
||||
: is ( xt "name" -- )
|
||||
tcompile? if
|
||||
' >body @ do-number
|
||||
s" ! " evaluate
|
||||
else
|
||||
' execute t!
|
||||
then ;
|
||||
|
||||
: ' ' execute ;
|
||||
|
||||
( VALUE JCB 13:06 11/12/10)
|
||||
|
||||
: value
|
||||
wordstr setlabel
|
||||
create there , t,
|
||||
does> @ do-number s" @" evaluate ;
|
||||
|
||||
: to ( u "name" -- )
|
||||
' >body @ do-number s" !" evaluate ;
|
||||
|
||||
( ARRAY JCB 13:34 11/12/10)
|
||||
|
||||
: array
|
||||
wordstr setlabel
|
||||
create there , 0 do 0 t, loop
|
||||
does> s" cells" evaluate @ do-number s" +" evaluate ;
|
||||
: 2array
|
||||
wordstr setlabel
|
||||
create there , 2* 0 do 0 t, loop
|
||||
does> s" 2* cells" evaluate @ do-number s" +" evaluate ;
|
||||
|
||||
( eforth's way of handling constants JCB 13:12 09/03/10)
|
||||
|
||||
: sign>number
|
||||
over c@ [char] - = if
|
||||
1- swap 1+ swap
|
||||
>number
|
||||
2swap dnegate 2swap
|
||||
else
|
||||
>number
|
||||
then
|
||||
;
|
||||
|
||||
: base>number ( caddr u base -- )
|
||||
base @ >r base !
|
||||
sign>number
|
||||
r> base !
|
||||
dup 0= if
|
||||
2drop drop do-number
|
||||
else
|
||||
1 = swap c@ [char] . = and if
|
||||
drop dup do-number 16 rshift do-number
|
||||
else
|
||||
-1 abort" bad number"
|
||||
then
|
||||
then ;
|
||||
|
||||
: d# 0. bl parse 10 base>number ;
|
||||
: h# 0. bl parse 16 base>number ;
|
||||
|
||||
( Conditionals JCB 13:12 09/03/10)
|
||||
: if
|
||||
there
|
||||
0 0branch
|
||||
;
|
||||
|
||||
: resolve
|
||||
dup t@ there 2/ or swap t!
|
||||
;
|
||||
|
||||
: then
|
||||
resolve
|
||||
s" (then)" setlabel
|
||||
;
|
||||
|
||||
: else
|
||||
there
|
||||
0 ubranch
|
||||
swap resolve
|
||||
s" (else)" setlabel
|
||||
;
|
||||
|
||||
|
||||
: begin s" (begin)" setlabel there ;
|
||||
: again
|
||||
ubranch
|
||||
;
|
||||
: until
|
||||
0branch
|
||||
;
|
||||
: while
|
||||
there
|
||||
0 0branch
|
||||
;
|
||||
: repeat
|
||||
swap ubranch
|
||||
resolve
|
||||
s" (repeat)" setlabel
|
||||
;
|
||||
|
||||
: 0do s" >r d# 0 >r" evaluate there s" (do)" setlabel ;
|
||||
: do s" 2>r" evaluate there s" (do)" setlabel ;
|
||||
: loop
|
||||
s" looptest" evaluate 0branch
|
||||
;
|
||||
: i s" r@" evaluate ;
|
||||
|
||||
77 constant sourceline#
|
||||
s" none" 2constant sourcefilename
|
||||
|
||||
: line# sourceline# (literal) ;
|
||||
create currfilename 1 cells 80 + allot
|
||||
variable currfilename#
|
||||
: savestr ( c-addr u dst -- ) 2dup c! 1+ swap cmove ;
|
||||
: getfilename sourcefilename currfilename count compare 0<>
|
||||
if
|
||||
sourcefilename 2dup currfilename savestr (sliteral--h) currfilename# !
|
||||
else
|
||||
currfilename# @ dup 1+ (literal) tc@ (literal)
|
||||
then ;
|
||||
: snap line# getfilename s" (snap)" evaluate ; immediate
|
||||
: assert 0= if line# sourcefilename (sliteral) s" (assert)" evaluate then ; immediate
|
||||
70
j1/firmware/defines_tcpip.fs
Normal file
70
j1/firmware/defines_tcpip.fs
Normal file
@ -0,0 +1,70 @@
|
||||
42 constant OFFSET_DHCP
|
||||
70 constant OFFSET_DHCP_CHADDR
|
||||
54 constant OFFSET_DHCP_CIADDR
|
||||
150 constant OFFSET_DHCP_FILE
|
||||
52 constant OFFSET_DHCP_FLAGS
|
||||
66 constant OFFSET_DHCP_GIADDR
|
||||
44 constant OFFSET_DHCP_HLEN
|
||||
45 constant OFFSET_DHCP_HOPS
|
||||
43 constant OFFSET_DHCP_HTYPE
|
||||
42 constant OFFSET_DHCP_OP
|
||||
278 constant OFFSET_DHCP_OPTIONS
|
||||
50 constant OFFSET_DHCP_SECS
|
||||
62 constant OFFSET_DHCP_SIADDR
|
||||
548 constant OFFSET_DHCP_SIZE
|
||||
86 constant OFFSET_DHCP_SNAME
|
||||
46 constant OFFSET_DHCP_XID
|
||||
58 constant OFFSET_DHCP_YIADDR
|
||||
42 constant OFFSET_DNS
|
||||
44 constant OFFSET_DNS_FLAGS
|
||||
42 constant OFFSET_DNS_IDENTIFICATION
|
||||
48 constant OFFSET_DNS_NOA
|
||||
52 constant OFFSET_DNS_NOARR
|
||||
46 constant OFFSET_DNS_NOQ
|
||||
50 constant OFFSET_DNS_NORR
|
||||
54 constant OFFSET_DNS_QUERY
|
||||
13 constant OFFSET_DNS_SIZE
|
||||
0 constant OFFSET_ETH
|
||||
0 constant OFFSET_ETH_DST
|
||||
14 constant OFFSET_ETH_SIZE
|
||||
6 constant OFFSET_ETH_SRC
|
||||
12 constant OFFSET_ETH_TYPE
|
||||
34 constant OFFSET_ICMP
|
||||
36 constant OFFSET_ICMP_CHKSUM
|
||||
38 constant OFFSET_ICMP_IDENTIFIER
|
||||
40 constant OFFSET_ICMP_SEQUENCE
|
||||
8 constant OFFSET_ICMP_SIZE
|
||||
34 constant OFFSET_ICMP_TYPECODE
|
||||
14 constant OFFSET_IP
|
||||
24 constant OFFSET_IP_CHKSUM
|
||||
30 constant OFFSET_IP_DSTIP
|
||||
18 constant OFFSET_IP_IPID
|
||||
20 constant OFFSET_IP_IPOFFSET
|
||||
16 constant OFFSET_IP_LENGTH
|
||||
20 constant OFFSET_IP_SIZE
|
||||
26 constant OFFSET_IP_SRCIP
|
||||
22 constant OFFSET_IP_TTLPROTO
|
||||
14 constant OFFSET_IP_VHLTOS
|
||||
42 constant OFFSET_JUICE
|
||||
68 constant OFFSET_JUICE_COMMAND
|
||||
42 constant OFFSET_JUICE_HASH
|
||||
62 constant OFFSET_JUICE_MAGIC
|
||||
70 constant OFFSET_JUICE_PAYLOAD
|
||||
66 constant OFFSET_JUICE_SEQ
|
||||
30 constant OFFSET_JUICE_SIZE
|
||||
34 constant OFFSET_TCP
|
||||
42 constant OFFSET_TCP_ACK
|
||||
50 constant OFFSET_TCP_CHECKSUM
|
||||
36 constant OFFSET_TCP_DESTPORT
|
||||
46 constant OFFSET_TCP_FLAGS
|
||||
38 constant OFFSET_TCP_SEQNUM
|
||||
20 constant OFFSET_TCP_SIZE
|
||||
34 constant OFFSET_TCP_SOURCEPORT
|
||||
52 constant OFFSET_TCP_URGENT
|
||||
48 constant OFFSET_TCP_WINDOW
|
||||
34 constant OFFSET_UDP
|
||||
40 constant OFFSET_UDP_CHECKSUM
|
||||
36 constant OFFSET_UDP_DESTPORT
|
||||
38 constant OFFSET_UDP_LENGTH
|
||||
8 constant OFFSET_UDP_SIZE
|
||||
34 constant OFFSET_UDP_SOURCEPORT
|
||||
94
j1/firmware/defines_tcpip.py
Normal file
94
j1/firmware/defines_tcpip.py
Normal file
@ -0,0 +1,94 @@
|
||||
layout = [
|
||||
('ETH', [
|
||||
('DST', 6),
|
||||
('SRC', 6),
|
||||
('TYPE', 2),
|
||||
[
|
||||
('IP', [
|
||||
('VHLTOS', 2),
|
||||
('LENGTH', 2),
|
||||
('IPID', 2),
|
||||
('IPOFFSET', 2),
|
||||
('TTLPROTO', 2),
|
||||
('CHKSUM', 2),
|
||||
('SRCIP', 4),
|
||||
('DSTIP', 4),
|
||||
[
|
||||
('ICMP', [
|
||||
('TYPECODE', 2),
|
||||
('CHKSUM', 2),
|
||||
('IDENTIFIER', 2),
|
||||
('SEQUENCE', 2) ]),
|
||||
('TCP', [
|
||||
('SOURCEPORT', 2),
|
||||
('DESTPORT', 2),
|
||||
('SEQNUM', 4),
|
||||
('ACK', 4),
|
||||
('FLAGS', 2),
|
||||
('WINDOW', 2),
|
||||
('CHECKSUM', 2),
|
||||
('URGENT', 2) ]),
|
||||
('UDP', [
|
||||
('SOURCEPORT', 2),
|
||||
('DESTPORT', 2),
|
||||
('LENGTH', 2),
|
||||
('CHECKSUM', 2),
|
||||
[
|
||||
('DHCP', [
|
||||
('OP', 1),
|
||||
('HTYPE', 1),
|
||||
('HLEN', 1),
|
||||
('HOPS', 1),
|
||||
('XID', 4),
|
||||
('SECS', 2),
|
||||
('FLAGS', 2),
|
||||
('CIADDR', 4),
|
||||
('YIADDR', 4),
|
||||
('SIADDR', 4),
|
||||
('GIADDR', 4),
|
||||
('CHADDR', 16),
|
||||
('SNAME', 64),
|
||||
('FILE', 128),
|
||||
('OPTIONS', 312)
|
||||
]),
|
||||
('DNS', [
|
||||
('IDENTIFICATION', 2),
|
||||
('FLAGS', 2),
|
||||
('NOQ', 2),
|
||||
('NOA', 2),
|
||||
('NORR', 2),
|
||||
('NOARR', 2),
|
||||
('QUERY', 1)
|
||||
]),
|
||||
('JUICE', [
|
||||
('HASH', 20),
|
||||
('MAGIC', 4),
|
||||
('SEQ', 2),
|
||||
('COMMAND', 2),
|
||||
('PAYLOAD', 2)
|
||||
])
|
||||
]
|
||||
])
|
||||
]
|
||||
])
|
||||
]])
|
||||
]
|
||||
|
||||
offsets = {}
|
||||
def descend(offset, prefix, node):
|
||||
(name, members) = node
|
||||
offsets[prefix + name] = offset
|
||||
start = offset
|
||||
for m in members:
|
||||
if isinstance(m, tuple):
|
||||
(field, size) = m
|
||||
# print prefix, name, field, offset
|
||||
offsets["%s%s_%s" % (prefix, name, field)] = offset
|
||||
offset += size
|
||||
else:
|
||||
for n in m:
|
||||
descend(offset, prefix, n)
|
||||
# print prefix, name, "SIZE", offset - start
|
||||
offsets["%s%s_SIZE" % (prefix, name)] = offset - start
|
||||
|
||||
descend(0, 'OFFSET_', layout[0])
|
||||
150
j1/firmware/defines_tcpip2.fs
Normal file
150
j1/firmware/defines_tcpip2.fs
Normal file
@ -0,0 +1,150 @@
|
||||
0 constant ETH
|
||||
14 constant ETH.ARP
|
||||
32 constant ETH.ARP.DST_ETH
|
||||
38 constant ETH.ARP.DST_IP
|
||||
20 constant ETH.ARP.OPCODE
|
||||
14 constant ETH.ARP.SOMETHING
|
||||
22 constant ETH.ARP.SRC_ETH
|
||||
28 constant ETH.ARP.SRC_IP
|
||||
0 constant ETH.DST
|
||||
14 constant ETH.IP
|
||||
24 constant ETH.IP.CHKSUM
|
||||
30 constant ETH.IP.DSTIP
|
||||
34 constant ETH.IP.ICMP
|
||||
36 constant ETH.IP.ICMP.CHKSUM
|
||||
38 constant ETH.IP.ICMP.IDENTIFIER
|
||||
40 constant ETH.IP.ICMP.SEQUENCE
|
||||
34 constant ETH.IP.ICMP.TYPECODE
|
||||
18 constant ETH.IP.IPID
|
||||
20 constant ETH.IP.IPOFFSET
|
||||
16 constant ETH.IP.LENGTH
|
||||
26 constant ETH.IP.SRCIP
|
||||
34 constant ETH.IP.TCP
|
||||
42 constant ETH.IP.TCP.ACK
|
||||
50 constant ETH.IP.TCP.CHECKSUM
|
||||
36 constant ETH.IP.TCP.DESTPORT
|
||||
46 constant ETH.IP.TCP.FLAGS
|
||||
38 constant ETH.IP.TCP.SEQNUM
|
||||
34 constant ETH.IP.TCP.SOURCEPORT
|
||||
52 constant ETH.IP.TCP.URGENT
|
||||
48 constant ETH.IP.TCP.WINDOW
|
||||
22 constant ETH.IP.TTLPROTO
|
||||
34 constant ETH.IP.UDP
|
||||
40 constant ETH.IP.UDP.CHECKSUM
|
||||
36 constant ETH.IP.UDP.DESTPORT
|
||||
42 constant ETH.IP.UDP.DHCP
|
||||
70 constant ETH.IP.UDP.DHCP.CHADDR
|
||||
54 constant ETH.IP.UDP.DHCP.CIADDR
|
||||
150 constant ETH.IP.UDP.DHCP.FILE
|
||||
52 constant ETH.IP.UDP.DHCP.FLAGS
|
||||
66 constant ETH.IP.UDP.DHCP.GIADDR
|
||||
44 constant ETH.IP.UDP.DHCP.HLEN
|
||||
45 constant ETH.IP.UDP.DHCP.HOPS
|
||||
43 constant ETH.IP.UDP.DHCP.HTYPE
|
||||
42 constant ETH.IP.UDP.DHCP.OP
|
||||
278 constant ETH.IP.UDP.DHCP.OPTIONS
|
||||
50 constant ETH.IP.UDP.DHCP.SECS
|
||||
62 constant ETH.IP.UDP.DHCP.SIADDR
|
||||
86 constant ETH.IP.UDP.DHCP.SNAME
|
||||
46 constant ETH.IP.UDP.DHCP.XID
|
||||
58 constant ETH.IP.UDP.DHCP.YIADDR
|
||||
42 constant ETH.IP.UDP.DNS
|
||||
44 constant ETH.IP.UDP.DNS.FLAGS
|
||||
42 constant ETH.IP.UDP.DNS.IDENTIFICATION
|
||||
48 constant ETH.IP.UDP.DNS.NOA
|
||||
52 constant ETH.IP.UDP.DNS.NOARR
|
||||
46 constant ETH.IP.UDP.DNS.NOQ
|
||||
50 constant ETH.IP.UDP.DNS.NORR
|
||||
54 constant ETH.IP.UDP.DNS.QUERY
|
||||
38 constant ETH.IP.UDP.LENGTH
|
||||
42 constant ETH.IP.UDP.LOADER
|
||||
46 constant ETH.IP.UDP.LOADER.FLASHREAD
|
||||
46 constant ETH.IP.UDP.LOADER.FLASHREAD.ADDR
|
||||
46 constant ETH.IP.UDP.LOADER.FLASHWRITE
|
||||
46 constant ETH.IP.UDP.LOADER.FLASHWRITE.ADDR
|
||||
50 constant ETH.IP.UDP.LOADER.FLASHWRITE.DATA
|
||||
44 constant ETH.IP.UDP.LOADER.OPCODE
|
||||
46 constant ETH.IP.UDP.LOADER.RAMREAD
|
||||
46 constant ETH.IP.UDP.LOADER.RAMREAD.ADDR
|
||||
46 constant ETH.IP.UDP.LOADER.RAMWRITE
|
||||
46 constant ETH.IP.UDP.LOADER.RAMWRITE.ADDR
|
||||
48 constant ETH.IP.UDP.LOADER.RAMWRITE.DATA
|
||||
42 constant ETH.IP.UDP.LOADER.SEQNO
|
||||
42 constant ETH.IP.UDP.NTP
|
||||
42 constant ETH.IP.UDP.NTP.FLAGS
|
||||
66 constant ETH.IP.UDP.NTP.ORIGINATE
|
||||
74 constant ETH.IP.UDP.NTP.RECEIVE
|
||||
58 constant ETH.IP.UDP.NTP.REFERENCE
|
||||
54 constant ETH.IP.UDP.NTP.REFID
|
||||
46 constant ETH.IP.UDP.NTP.ROOTDELAY
|
||||
50 constant ETH.IP.UDP.NTP.ROOTDISPERSION
|
||||
82 constant ETH.IP.UDP.NTP.TRANSMIT
|
||||
34 constant ETH.IP.UDP.SOURCEPORT
|
||||
42 constant ETH.IP.UDP.TFTP
|
||||
44 constant ETH.IP.UDP.TFTP.ACK
|
||||
44 constant ETH.IP.UDP.TFTP.ACK.BLOCK
|
||||
44 constant ETH.IP.UDP.TFTP.DATA
|
||||
44 constant ETH.IP.UDP.TFTP.DATA.BLOCK
|
||||
46 constant ETH.IP.UDP.TFTP.DATA.DATA
|
||||
44 constant ETH.IP.UDP.TFTP.ERROR
|
||||
46 constant ETH.IP.UDP.TFTP.ERROR.MESSAGE
|
||||
44 constant ETH.IP.UDP.TFTP.ERROR.NUMBER
|
||||
42 constant ETH.IP.UDP.TFTP.OPCODE
|
||||
44 constant ETH.IP.UDP.TFTP.RWRQ
|
||||
44 constant ETH.IP.UDP.TFTP.RWRQ.FILENAME
|
||||
42 constant ETH.IP.UDP.WGE
|
||||
82 constant ETH.IP.UDP.WGE.CONFIGURE
|
||||
90 constant ETH.IP.UDP.WGE.CONFIGURE.IP
|
||||
82 constant ETH.IP.UDP.WGE.CONFIGURE.PRODUCT
|
||||
86 constant ETH.IP.UDP.WGE.CONFIGURE.SERIAL
|
||||
82 constant ETH.IP.UDP.WGE.DISCOVER
|
||||
82 constant ETH.IP.UDP.WGE.DISCOVER.IP
|
||||
82 constant ETH.IP.UDP.WGE.FLASHREAD
|
||||
82 constant ETH.IP.UDP.WGE.FLASHREAD.ADDRESS
|
||||
82 constant ETH.IP.UDP.WGE.FLASHWRITE
|
||||
82 constant ETH.IP.UDP.WGE.FLASHWRITE.ADDRESS
|
||||
86 constant ETH.IP.UDP.WGE.FLASHWRITE.DATA
|
||||
50 constant ETH.IP.UDP.WGE.HRT
|
||||
82 constant ETH.IP.UDP.WGE.IMAGERMODE
|
||||
82 constant ETH.IP.UDP.WGE.IMAGERMODE.MODE
|
||||
82 constant ETH.IP.UDP.WGE.IMAGERSETRES
|
||||
82 constant ETH.IP.UDP.WGE.IMAGERSETRES.HORIZONTAL
|
||||
84 constant ETH.IP.UDP.WGE.IMAGERSETRES.VERTICAL
|
||||
42 constant ETH.IP.UDP.WGE.MAGIC
|
||||
80 constant ETH.IP.UDP.WGE.PAD
|
||||
66 constant ETH.IP.UDP.WGE.REPLYTO
|
||||
74 constant ETH.IP.UDP.WGE.REPLYTO.IP
|
||||
66 constant ETH.IP.UDP.WGE.REPLYTO.MAC
|
||||
78 constant ETH.IP.UDP.WGE.REPLYTO.PORT
|
||||
82 constant ETH.IP.UDP.WGE.SENSORREAD
|
||||
82 constant ETH.IP.UDP.WGE.SENSORREAD.ADDRESS
|
||||
82 constant ETH.IP.UDP.WGE.SENSORSELECT
|
||||
83 constant ETH.IP.UDP.WGE.SENSORSELECT.ADDRESS
|
||||
82 constant ETH.IP.UDP.WGE.SENSORSELECT.INDEX
|
||||
82 constant ETH.IP.UDP.WGE.SENSORWRITE
|
||||
82 constant ETH.IP.UDP.WGE.SENSORWRITE.ADDRESS
|
||||
83 constant ETH.IP.UDP.WGE.SENSORWRITE.DATA
|
||||
82 constant ETH.IP.UDP.WGE.SYSCONFIG
|
||||
82 constant ETH.IP.UDP.WGE.SYSCONFIG.MAC
|
||||
88 constant ETH.IP.UDP.WGE.SYSCONFIG.SERIAL
|
||||
82 constant ETH.IP.UDP.WGE.TRIGCONTROL
|
||||
82 constant ETH.IP.UDP.WGE.TRIGCONTROL.TRIGSTATE
|
||||
46 constant ETH.IP.UDP.WGE.TYPE
|
||||
82 constant ETH.IP.UDP.WGE.VIDSTART
|
||||
90 constant ETH.IP.UDP.WGE.VIDSTART.IP
|
||||
82 constant ETH.IP.UDP.WGE.VIDSTART.MAC
|
||||
94 constant ETH.IP.UDP.WGE.VIDSTART.PORT
|
||||
14 constant ETH.IP.VHLTOS
|
||||
6 constant ETH.SRC
|
||||
12 constant ETH.TYPE
|
||||
1 constant IP_PROTO_ICMP
|
||||
2 constant IP_PROTO_IGMP
|
||||
6 constant IP_PROTO_TCP
|
||||
17 constant IP_PROTO_UDP
|
||||
2 constant NUM_TCPS
|
||||
16 constant TCP_ACK
|
||||
1 constant TCP_FIN
|
||||
8 constant TCP_PSH
|
||||
4 constant TCP_RST
|
||||
2 constant TCP_SYN
|
||||
32 constant TCP_URG
|
||||
215
j1/firmware/defines_tcpip2.py
Normal file
215
j1/firmware/defines_tcpip2.py
Normal file
@ -0,0 +1,215 @@
|
||||
layout = [
|
||||
('ETH', [
|
||||
('DST', 6),
|
||||
('SRC', 6),
|
||||
('TYPE', 2),
|
||||
[
|
||||
('ARP', [
|
||||
('SOMETHING', 6),
|
||||
('OPCODE', 2),
|
||||
('SRC_ETH', 6),
|
||||
('SRC_IP', 4),
|
||||
('DST_ETH', 6),
|
||||
('DST_IP', 4) ]),
|
||||
('IP', [
|
||||
('VHLTOS', 2),
|
||||
('LENGTH', 2),
|
||||
('IPID', 2),
|
||||
('IPOFFSET', 2),
|
||||
('TTLPROTO', 2),
|
||||
('CHKSUM', 2),
|
||||
('SRCIP', 4),
|
||||
('DSTIP', 4),
|
||||
[
|
||||
('ICMP', [
|
||||
('TYPECODE', 2),
|
||||
('CHKSUM', 2),
|
||||
('IDENTIFIER', 2),
|
||||
('SEQUENCE', 2) ]),
|
||||
('TCP', [
|
||||
('SOURCEPORT', 2),
|
||||
('DESTPORT', 2),
|
||||
('SEQNUM', 4),
|
||||
('ACK', 4),
|
||||
('FLAGS', 2),
|
||||
('WINDOW', 2),
|
||||
('CHECKSUM', 2),
|
||||
('URGENT', 2) ]),
|
||||
('UDP', [
|
||||
('SOURCEPORT', 2),
|
||||
('DESTPORT', 2),
|
||||
('LENGTH', 2),
|
||||
('CHECKSUM', 2),
|
||||
[
|
||||
('DHCP', [
|
||||
('OP', 1),
|
||||
('HTYPE', 1),
|
||||
('HLEN', 1),
|
||||
('HOPS', 1),
|
||||
('XID', 4),
|
||||
('SECS', 2),
|
||||
('FLAGS', 2),
|
||||
('CIADDR', 4),
|
||||
('YIADDR', 4),
|
||||
('SIADDR', 4),
|
||||
('GIADDR', 4),
|
||||
('CHADDR', 16),
|
||||
('SNAME', 64),
|
||||
('FILE', 128),
|
||||
('OPTIONS', 312)
|
||||
]),
|
||||
('DNS', [
|
||||
('IDENTIFICATION', 2),
|
||||
('FLAGS', 2),
|
||||
('NOQ', 2),
|
||||
('NOA', 2),
|
||||
('NORR', 2),
|
||||
('NOARR', 2),
|
||||
('QUERY', 1)
|
||||
]),
|
||||
('NTP', [
|
||||
('FLAGS', 4),
|
||||
('ROOTDELAY', 4),
|
||||
('ROOTDISPERSION', 4),
|
||||
('REFID', 4),
|
||||
('REFERENCE', 8),
|
||||
('ORIGINATE', 8),
|
||||
('RECEIVE', 8),
|
||||
('TRANSMIT', 8),
|
||||
]),
|
||||
('TFTP', [
|
||||
('OPCODE', 2),
|
||||
[
|
||||
('RWRQ', [
|
||||
('FILENAME', 512)
|
||||
]),
|
||||
('DATA', [
|
||||
('BLOCK', 2),
|
||||
('DATA', 512)
|
||||
]),
|
||||
('ACK', [
|
||||
('BLOCK', 2),
|
||||
]),
|
||||
('ERROR', [
|
||||
('NUMBER', 2),
|
||||
('MESSAGE', 512),
|
||||
]),
|
||||
]
|
||||
]),
|
||||
('LOADER', [
|
||||
('SEQNO', 2),
|
||||
('OPCODE', 2),
|
||||
[
|
||||
('RAMREAD', [
|
||||
('ADDR', 2)
|
||||
]),
|
||||
('RAMWRITE', [
|
||||
('ADDR', 2),
|
||||
('DATA', 128)
|
||||
]),
|
||||
('FLASHREAD', [
|
||||
('ADDR', 4)
|
||||
]),
|
||||
('FLASHWRITE', [
|
||||
('ADDR', 4),
|
||||
('DATA', 128)
|
||||
]),
|
||||
]
|
||||
]),
|
||||
('WGE', [
|
||||
('MAGIC', 4),
|
||||
('TYPE', 4),
|
||||
('HRT', 16),
|
||||
('REPLYTO', [
|
||||
('MAC', 8),
|
||||
('IP', 4),
|
||||
('PORT', 2),
|
||||
]),
|
||||
('PAD', 2),
|
||||
[
|
||||
('DISCOVER', [
|
||||
('IP', 4)
|
||||
]),
|
||||
('CONFIGURE', [
|
||||
('PRODUCT', 4),
|
||||
('SERIAL', 4),
|
||||
('IP', 4)
|
||||
]),
|
||||
('FLASHREAD', [
|
||||
('ADDRESS', 4)
|
||||
]),
|
||||
('FLASHWRITE', [
|
||||
('ADDRESS', 4),
|
||||
('DATA', 264),
|
||||
]),
|
||||
('TRIGCONTROL', [
|
||||
('TRIGSTATE', 4),
|
||||
]),
|
||||
('SENSORREAD', [
|
||||
('ADDRESS', 1),
|
||||
]),
|
||||
('SENSORWRITE', [
|
||||
('ADDRESS', 1),
|
||||
('DATA', 2),
|
||||
]),
|
||||
('SENSORSELECT', [
|
||||
('INDEX', 1),
|
||||
('ADDRESS', 4),
|
||||
]),
|
||||
('IMAGERMODE', [
|
||||
('MODE', 4),
|
||||
]),
|
||||
('IMAGERSETRES', [
|
||||
('HORIZONTAL', 2),
|
||||
('VERTICAL', 2),
|
||||
]),
|
||||
('SYSCONFIG', [
|
||||
('MAC', 6),
|
||||
('SERIAL', 4),
|
||||
]),
|
||||
('VIDSTART', [
|
||||
('MAC', 8),
|
||||
('IP', 4),
|
||||
('PORT', 2),
|
||||
]),
|
||||
]
|
||||
]),
|
||||
]
|
||||
])
|
||||
]
|
||||
])
|
||||
]])
|
||||
]
|
||||
|
||||
offsets = {}
|
||||
def descend(offset, prefix, node):
|
||||
start = offset
|
||||
if isinstance(node, list):
|
||||
for n in node:
|
||||
descend(offset, prefix, n)
|
||||
else:
|
||||
(name, members) = node
|
||||
offsets[".".join((prefix + [name]))] = offset
|
||||
if isinstance(members, int):
|
||||
offset += members
|
||||
else:
|
||||
for n in members:
|
||||
offset = descend(offset, prefix + [name], n)
|
||||
# offsets["%s%s_SIZE" % (prefix, name)] = offset - start
|
||||
return offset
|
||||
|
||||
descend(0, [], layout[0])
|
||||
|
||||
offsets['TCP_FIN'] = 1
|
||||
offsets['TCP_SYN'] = 2
|
||||
offsets['TCP_RST'] = 4
|
||||
offsets['TCP_PSH'] = 8
|
||||
offsets['TCP_ACK'] = 16
|
||||
offsets['TCP_URG'] = 32
|
||||
|
||||
offsets['IP_PROTO_ICMP'] = 1
|
||||
offsets['IP_PROTO_IGMP'] = 2
|
||||
offsets['IP_PROTO_TCP'] = 6
|
||||
offsets['IP_PROTO_UDP'] = 17
|
||||
|
||||
offsets['NUM_TCPS'] = 2
|
||||
176
j1/firmware/dhcp.fs
Normal file
176
j1/firmware/dhcp.fs
Normal file
@ -0,0 +1,176 @@
|
||||
( DHCP: Dynamic Host Configuration Protocol JCB 13:13 08/24/10)
|
||||
module[ dhcp"
|
||||
|
||||
\ Since DHCP alarm is only used when there is no lease, it is
|
||||
\ safe to use the ip-subnetmask for the same purpose.
|
||||
|
||||
ip-subnetmask constant dhcp-alarm
|
||||
|
||||
: dhcp-xid
|
||||
ip-router 2@
|
||||
;
|
||||
|
||||
: dhcp-xid!
|
||||
ip-router 2!
|
||||
;
|
||||
|
||||
: dhcp-option \ ( ... n code -- )
|
||||
mac-pkt-c,
|
||||
dup mac-pkt-c,
|
||||
0do
|
||||
mac-pkt-c,
|
||||
loop
|
||||
;
|
||||
|
||||
: dhcp-common \ ( messagetype -- )
|
||||
d# 67 d# 68
|
||||
d# 0 invert dup
|
||||
d# 0 dup
|
||||
d# 0 \ broadcast ethaddr
|
||||
( dst-port src-port dst-ip src-ip *ethaddr -- )
|
||||
udp-header
|
||||
h# 0101 h# 0600 mac-pkt-2,
|
||||
dhcp-xid mac-pkt-2,
|
||||
d# 10 mac-pkt-,0
|
||||
net-my-mac mac-pkt-3,
|
||||
d# 101 mac-pkt-,0 \ d# 5 + d# 96 zeroes
|
||||
|
||||
h# 6382 h# 5363
|
||||
mac-pkt-2,
|
||||
|
||||
\ DHCP option 53: DHCP Discover
|
||||
\ messagetype
|
||||
d# 1 d# 53 \ messagetype 1 53
|
||||
dhcp-option
|
||||
|
||||
\ DHCP option 50: 192.168.1.100 requested
|
||||
|
||||
\ DHCP option 55: Parameter Request List:
|
||||
\ Request Subnet Mask (1), Router (3),
|
||||
\ Domain Name Server (6)
|
||||
d# 1 d# 3 d# 6 d# 3 d# 55 dhcp-option
|
||||
;
|
||||
|
||||
: dhcp-wrapup
|
||||
\ Finish options
|
||||
h# ff mac-pkt-c,
|
||||
\ mac-wrptr @ d# 1 and
|
||||
d# 1 if \ XXX
|
||||
h# ff mac-pkt-c,
|
||||
then
|
||||
|
||||
udp-wrapup
|
||||
mac-send
|
||||
;
|
||||
|
||||
\ memory layout is little-endian
|
||||
|
||||
: macc@++ ( c-addr -- c-addr+1 c )
|
||||
dup 1+ swap macc@ ;
|
||||
|
||||
: dhcp-field \ ( match -- ptr/0 )
|
||||
OFFSET_DHCP_OPTIONS d# 4 + mac-inoffset
|
||||
\ match ptr
|
||||
begin
|
||||
macc@++ \ match ptr code
|
||||
dup h# ff <>
|
||||
while \ match ptr code
|
||||
d# 2 pick =
|
||||
if
|
||||
nip \ ptr
|
||||
exit
|
||||
then \ match ptr
|
||||
macc@++ + \ match ptr'
|
||||
repeat
|
||||
\ fail - return false
|
||||
2drop false
|
||||
;
|
||||
|
||||
: dhcp-yiaddr
|
||||
d# 2 OFFSET_DHCP_YIADDR mac-inoffset mac@n
|
||||
;
|
||||
|
||||
: dhcp-field4
|
||||
dhcp-field d# 1 +
|
||||
macc@++ swap macc@++ swap macc@++ swap macc@
|
||||
( a b c d )
|
||||
swap d# 8 lshift or -rot
|
||||
swap d# 8 lshift or
|
||||
swap
|
||||
;
|
||||
|
||||
build-debug? [IF]
|
||||
: .pad ( ip. c-addr u -- ) d# 14 typepad ip-pretty cr ;
|
||||
|
||||
: dhcp-status
|
||||
ip-addr 2@ s" IP" .pad
|
||||
ip-router 2@ s" router" .pad
|
||||
ip-subnetmask 2@ s" subnetmask" .pad
|
||||
;
|
||||
[ELSE]
|
||||
: dhcp-status ;
|
||||
[THEN]
|
||||
|
||||
: lease-setalarm
|
||||
d# 0 >r
|
||||
begin
|
||||
2dup d# 63. d>
|
||||
while
|
||||
d2/ r> 1+ >r
|
||||
repeat
|
||||
r>
|
||||
hex4 space hex8 cr
|
||||
;
|
||||
|
||||
: dhcp-wait-offer
|
||||
h# 11 ip-isproto
|
||||
OFFSET_UDP_SOURCEPORT packet@ d# 67 = and
|
||||
OFFSET_UDP_DESTPORT packet@ d# 68 = and
|
||||
d# 2 OFFSET_DHCP_XID mac-inoffset mac@n dhcp-xid d= and
|
||||
if
|
||||
snap
|
||||
d# 53 dhcp-field ?dup
|
||||
snap
|
||||
if
|
||||
d# 1 + macc@
|
||||
snap
|
||||
dup d# 2 =
|
||||
if
|
||||
\ [char] % emit
|
||||
d# 3 dhcp-common
|
||||
|
||||
\ option 50: request IP
|
||||
h# 3204
|
||||
dhcp-yiaddr
|
||||
mac-pkt-3,
|
||||
|
||||
\ Option 54: server
|
||||
h# 3604
|
||||
d# 54 dhcp-field4
|
||||
mac-pkt-3,
|
||||
|
||||
dhcp-wrapup
|
||||
then
|
||||
d# 5 =
|
||||
if
|
||||
\ clrwdt
|
||||
\ [char] & emit
|
||||
|
||||
dhcp-yiaddr ip-addr 2!
|
||||
d# 1 dhcp-field4 ip-subnetmask 2!
|
||||
\ For the router and DNS server, send out ARP requests right now. This
|
||||
\ reduces start-up time.
|
||||
d# 3 dhcp-field4 2dup ip-router 2! arp-lookup drop
|
||||
d# 6 dhcp-field4 2dup ip-dns 2! arp-lookup drop
|
||||
\ Option 51: lease time
|
||||
s" expires in " type
|
||||
d# 51 dhcp-field4 swap d. cr
|
||||
then
|
||||
then
|
||||
snap
|
||||
then
|
||||
;
|
||||
|
||||
: dhcp-discover d# 1 dhcp-common dhcp-wrapup ;
|
||||
|
||||
]module
|
||||
81
j1/firmware/dns.fs
Normal file
81
j1/firmware/dns.fs
Normal file
@ -0,0 +1,81 @@
|
||||
( DNS JCB 19:44 11/27/10)
|
||||
module[ dns"
|
||||
|
||||
: ip-dns@ ip-dns 2@ ;
|
||||
|
||||
\ ( offset -- offset' ) advance pointer past DNS label
|
||||
\ 0 means end
|
||||
\ >h# c0 means ptr to end
|
||||
\ N means word of N bytes
|
||||
|
||||
: dns-skiplabel
|
||||
begin
|
||||
dup 1+ swap mac-inoffset macc@ \ offset+1 v
|
||||
dup 0= if
|
||||
drop exit
|
||||
then
|
||||
dup h# c0 >= if
|
||||
drop 1+ exit
|
||||
then
|
||||
+
|
||||
again
|
||||
;
|
||||
|
||||
\ Query DNS. xt is a word that appends domainname to packet. id is DNS
|
||||
\ id field, used to route responses.
|
||||
|
||||
: dns-query ( xt id -- )
|
||||
>r
|
||||
\ dst-port src-port dst-ip src-ip *ethaddr
|
||||
d# 53 d# 31947
|
||||
ip-dns@
|
||||
net-my-ip
|
||||
ip-dns@ arp-lookup
|
||||
udp-header
|
||||
r> \ IDENTIFICATION
|
||||
h# 0100 \ FLAGS
|
||||
d# 1 \ NOQ
|
||||
mac-pkt-3,
|
||||
d# 3 mac-pkt-,0
|
||||
|
||||
execute
|
||||
|
||||
d# 1 \ query type A
|
||||
dup \ query class internet
|
||||
mac-pkt-2,
|
||||
udp-wrapup
|
||||
|
||||
ip-dns@ arp-lookup if
|
||||
mac-send
|
||||
then
|
||||
;
|
||||
|
||||
: dns-handler ( srcport dstport -- 0 / ip. id 1 )
|
||||
d# 53 d# 31947 d=
|
||||
OFFSET_DNS_FLAGS packet@ 0< and
|
||||
OFFSET_DNS_NOA packet@ 0<> and
|
||||
if
|
||||
OFFSET_DNS_QUERY
|
||||
dns-skiplabel
|
||||
d# 4 +
|
||||
dns-skiplabel
|
||||
d# 10 +
|
||||
mac-inoffset d# 2 swap mac@n
|
||||
OFFSET_DNS_IDENTIFICATION packet@
|
||||
d# 1
|
||||
else
|
||||
d# 0
|
||||
then
|
||||
;
|
||||
|
||||
: dns-appendname ( str -- )
|
||||
dup mac-pkt-c,
|
||||
mac-pkt-s,
|
||||
;
|
||||
|
||||
: dns-append.com ( str -- )
|
||||
dns-appendname
|
||||
s" com" dns-appendname
|
||||
d# 0 mac-pkt-c,
|
||||
;
|
||||
]module
|
||||
20
j1/firmware/doc.fs
Normal file
20
j1/firmware/doc.fs
Normal file
@ -0,0 +1,20 @@
|
||||
( Documentation conventions JCB 14:37 10/26/10)
|
||||
|
||||
meta
|
||||
|
||||
: getword ( -- a u )
|
||||
begin
|
||||
bl word count dup 0=
|
||||
while
|
||||
2drop refill true <> abort" Failed to find word"
|
||||
repeat
|
||||
;
|
||||
|
||||
: ================================================================
|
||||
begin
|
||||
getword
|
||||
nip 64 =
|
||||
until
|
||||
;
|
||||
|
||||
target
|
||||
3
j1/firmware/document.fs
Normal file
3
j1/firmware/document.fs
Normal file
@ -0,0 +1,3 @@
|
||||
\ For use with docforth.fs
|
||||
|
||||
s" ans.fs" included
|
||||
28
j1/firmware/encode.py
Normal file
28
j1/firmware/encode.py
Normal file
@ -0,0 +1,28 @@
|
||||
import sys
|
||||
import Image
|
||||
from array import array
|
||||
|
||||
def getch(im, x, y):
|
||||
return tuple(tuple((int(0 != im.getpixel((x + j, y + i)))) for j in range(8)) for i in range(8))
|
||||
|
||||
def main(filename):
|
||||
sm = Image.open(filename).convert("L")
|
||||
im = Image.new("L", (512, 256))
|
||||
im.paste(sm, (0,0))
|
||||
charset = {}
|
||||
picture = []
|
||||
for y in range(0, im.size[1], 8):
|
||||
for x in range(0, im.size[0], 8):
|
||||
glyph = getch(im, x, y)
|
||||
if not glyph in charset:
|
||||
charset[glyph] = 96 + len(charset)
|
||||
picture.append(charset[glyph])
|
||||
open(filename + ".pic", "w").write(array('B', picture).tostring())
|
||||
cd = array('B', [0] * 8 * len(charset))
|
||||
for d,i in charset.items():
|
||||
i -= 96
|
||||
for y in range(8):
|
||||
cd[8 * i + y] = sum([(d[y][x] << (7 - x)) for x in range(8)])
|
||||
open(filename + ".chr", "w").write(cd.tostring())
|
||||
|
||||
main(sys.argv[1])
|
||||
506
j1/firmware/eth-ax88796.fs
Normal file
506
j1/firmware/eth-ax88796.fs
Normal file
@ -0,0 +1,506 @@
|
||||
( Low-level MAC actions JCB 13:23 08/24/10)
|
||||
|
||||
================================================================
|
||||
|
||||
Initialization:
|
||||
mac-cold
|
||||
|
||||
Packet reception and reading:
|
||||
mac-fullness
|
||||
mac-inoffset
|
||||
mac@
|
||||
macc@
|
||||
mac@n
|
||||
mac-consume
|
||||
|
||||
Packet construction and transmission:
|
||||
mac-pkt-begin
|
||||
mac-pkt-,
|
||||
mac-pkt-c,
|
||||
mac-pkt-d,
|
||||
mac-pkt-2,
|
||||
mac-pkt-3,
|
||||
mac-pkt-,0
|
||||
mac-pkt-s,
|
||||
mac-pkt-src
|
||||
packetout-off
|
||||
mac!
|
||||
macc!
|
||||
mac-complete
|
||||
mac-checksum
|
||||
mac-send
|
||||
|
||||
================================================================
|
||||
|
||||
( NE2K JCB 10:23 11/08/10)
|
||||
|
||||
: ne2sel
|
||||
false ether_cs_n ! ;
|
||||
: ne2unsel
|
||||
true ether_cs_n ! ;
|
||||
: ne2a ( a -- )
|
||||
pb_a ! ;
|
||||
|
||||
: ne2rc@ ( a -- u ) \ NE2 byte reg read
|
||||
true ether_bhe_n !
|
||||
true ether_aen !
|
||||
ne2sel
|
||||
ne2a
|
||||
false pb_rd_n !
|
||||
\ pause144
|
||||
pb_d @ h# ff and
|
||||
true pb_rd_n !
|
||||
\ false ether_aen !
|
||||
\ ne2unsel
|
||||
;
|
||||
|
||||
: ne2rc! ( u a -- )
|
||||
\ over hex2 s" -> " type dup hex2 cr
|
||||
|
||||
true ether_bhe_n !
|
||||
|
||||
ne2sel
|
||||
ne2a
|
||||
pb_d !
|
||||
d# 0 ddir !
|
||||
false pb_wr_n !
|
||||
true pb_wr_n !
|
||||
\ ne2unsel
|
||||
d# 1 ddir !
|
||||
;
|
||||
|
||||
: ne2r! ( u a -- )
|
||||
over d# 8 rshift over 1+ ne2rc! ne2rc! ;
|
||||
|
||||
: ne2r. \ dump registers
|
||||
d# 16 0do
|
||||
d# 1000 0do pause144 loop
|
||||
i hex2 space
|
||||
i ne2rc@ hex4 cr
|
||||
loop
|
||||
;
|
||||
|
||||
h# 00 constant ne2-CR
|
||||
h# 01 constant ne2-PSTART
|
||||
h# 01 constant ne2-PAR0
|
||||
h# 03 constant ne2-PAR2
|
||||
h# 05 constant ne2-PAR4
|
||||
h# 01 constant ne2-CR9346
|
||||
h# 02 constant ne2-PSTOP
|
||||
h# 03 constant ne2-BNRY
|
||||
h# 04 constant ne2-TSR
|
||||
h# 04 constant ne2-TPSR
|
||||
h# 05 constant ne2-TBCR0
|
||||
h# 05 constant ne2-NCR
|
||||
h# 06 constant ne2-CPR
|
||||
h# 06 constant ne2-TBCR1
|
||||
h# 07 constant ne2-ISR
|
||||
h# 07 constant ne2-CURR
|
||||
h# 08 constant ne2-RSAR0
|
||||
h# 08 constant ne2-CRDA0
|
||||
h# 09 constant ne2-RSAR1
|
||||
h# 09 constant ne2-CRDA1
|
||||
h# 0A constant ne2-RBCR0
|
||||
h# 0B constant ne2-RBCR1
|
||||
h# 0C constant ne2-RSR
|
||||
h# 0C constant ne2-RCR
|
||||
h# 0D constant ne2-TCR
|
||||
h# 0D constant ne2-CNTR0
|
||||
h# 0E constant ne2-DCR
|
||||
h# 0E constant ne2-CNTR1
|
||||
h# 0F constant ne2-IMR
|
||||
h# 0F constant ne2-CNTR2
|
||||
h# 10 constant ne2-RDMAPORT
|
||||
h# 14 constant ne2-MIIEEP
|
||||
h# 15 constant ne2-TR
|
||||
h# 17 constant ne2-GPOC
|
||||
h# 17 constant ne2-GPI
|
||||
h# 1F constant ne2-RSTPORT
|
||||
|
||||
: ne2-page0 h# 22 ne2-CR ne2rc! ;
|
||||
: ne2-page1 h# 62 ne2-CR ne2rc! ;
|
||||
|
||||
: ne2-clrisr \ clear the ISR
|
||||
h# ff ne2-ISR ne2rc! ;
|
||||
|
||||
|
||||
: ne2r.2
|
||||
s" Page 0" type cr
|
||||
ne2-page0
|
||||
ne2r.
|
||||
s" Page 1" type cr
|
||||
ne2-page1
|
||||
ne2r.
|
||||
ne2-page0 ;
|
||||
|
||||
( The MII interface JCB 12:47 11/09/10)
|
||||
|
||||
h# 08 constant MII_EEP_MDO
|
||||
h# 04 constant MII_EEP_MDI
|
||||
h# 01 constant MII_EEP_MDC
|
||||
|
||||
: eep-on ( u ) ne2-MIIEEP ne2rc@ or ne2-MIIEEP ne2rc! ;
|
||||
: eep-off ( u ) invert ne2-MIIEEP ne2rc@ and ne2-MIIEEP ne2rc! ;
|
||||
|
||||
: miix ( u c -- u ) \ Send c bit data u
|
||||
tuck
|
||||
d# 16 swap - lshift
|
||||
swap
|
||||
0do
|
||||
MII_EEP_MDO over 0< if
|
||||
eep-on
|
||||
else
|
||||
eep-off
|
||||
then
|
||||
MII_EEP_MDC eep-on \ clock up
|
||||
2*
|
||||
ne2-MIIEEP ne2rc@ MII_EEP_MDI and if 1+ then
|
||||
MII_EEP_MDC eep-off \ clock down
|
||||
loop
|
||||
;
|
||||
|
||||
: phy@ ( a -- u )
|
||||
h# ffff d# 16 miix drop
|
||||
h# ffff d# 16 miix drop
|
||||
h# 0d0 d# 9 miix drop
|
||||
d# 5 miix drop
|
||||
h# 0 d# 1 miix drop
|
||||
h# 0 d# 16 miix
|
||||
;
|
||||
|
||||
: phy! ( u a -- )
|
||||
h# ffff d# 16 miix drop
|
||||
h# ffff d# 16 miix drop
|
||||
h# 0b0 d# 9 miix drop
|
||||
d# 5 miix drop
|
||||
h# 2 d# 2 miix drop
|
||||
d# 16 miix drop
|
||||
;
|
||||
|
||||
: phy.
|
||||
d# 32 0do
|
||||
i hex2 space i phy@ hex4 cr
|
||||
loop
|
||||
cr
|
||||
;
|
||||
|
||||
: phy-cold
|
||||
\ h# b000 d# 0 phy!
|
||||
h# 0800 d# 0 phy!
|
||||
s" PHY power down for 2.5s" type cr
|
||||
d# 2500000. sleepus
|
||||
\ h# 1200 d# 0 phy!
|
||||
h# 0000 d# 0 phy!
|
||||
exit
|
||||
sleep1
|
||||
sleep1
|
||||
sleep1
|
||||
sleep1
|
||||
sleep1
|
||||
sleep1
|
||||
|
||||
\ h# 6030 d# 30 phy!
|
||||
|
||||
phy. sleep1
|
||||
cr
|
||||
phy.
|
||||
;
|
||||
|
||||
: mac-cold ( ethaddr -- )
|
||||
|
||||
false RESET_TRIGGER !
|
||||
sleep1
|
||||
true RESET_TRIGGER !
|
||||
sleep1
|
||||
|
||||
true pb_rd_n !
|
||||
true pb_wr_n !
|
||||
true ether_cs_n !
|
||||
false ether_aen !
|
||||
true ether_bhe_n !
|
||||
d# 0 pb_a !
|
||||
d# 1 ddir !
|
||||
|
||||
\ d# 4 0do ne2-RSTPORT ne2rc@ ne2-RSTPORT ne2rc! sleep1 loop
|
||||
|
||||
phy-cold
|
||||
|
||||
\ Wait for TR RST_B to go low and GPI link up
|
||||
s" TR GPI" type cr
|
||||
begin
|
||||
ne2-TR ne2rc@ hex2 d# 3 spaces
|
||||
ne2-GPI ne2rc@ hex2 d# 3 spaces
|
||||
sleep.1
|
||||
cr
|
||||
ne2-TR ne2rc@ d# 2 and 0=
|
||||
ne2-GPI ne2rc@ d# 1 and 0<> and
|
||||
until
|
||||
|
||||
\ Wait for TR RST_B to go low
|
||||
\ begin
|
||||
\ sleep1
|
||||
\ ne2-TR ne2rc@ dup hex2 cr
|
||||
\ d# 2 and 0=
|
||||
\ until
|
||||
|
||||
true if
|
||||
h# 21 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 0
|
||||
h# 00 ne2-DCR ne2rc! \ Selects byte-wide DMA transfers
|
||||
h# 00 ne2-RBCR0 ne2rc! \ Load data byte count for remote DMA
|
||||
h# 00 ne2-RBCR1 ne2rc!
|
||||
h# 20 ne2-RCR ne2rc! \ Temporarily set receiver to monitor mode
|
||||
h# 02 ne2-TCR ne2rc! \ Transmitter set to internal loopback mode
|
||||
\ Initialize Receive Buffer Ring: Boundary Pointer
|
||||
\ (BNDRY), Page Start (PSTART), and Page Stop
|
||||
\ (PSTOP)
|
||||
h# 46 ne2-PSTART ne2rc!
|
||||
h# 46 ne2-BNRY ne2rc!
|
||||
h# 80 ne2-PSTOP ne2rc!
|
||||
h# ff ne2-ISR ne2rc! \ Clear Interrupt Status Register (ISR) by writing 0FFh to it.
|
||||
h# 01 ne2-IMR ne2rc! \ Initialize interrupt mask
|
||||
h# 61 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 1
|
||||
h# 12 d# 1 ne2rc! \ Set Physical Address
|
||||
h# 34 d# 2 ne2rc!
|
||||
h# 56 d# 3 ne2rc!
|
||||
h# 77 d# 4 ne2rc!
|
||||
h# 77 d# 5 ne2rc!
|
||||
h# 77 d# 6 ne2rc!
|
||||
d# 16 d# 8 do \ Set multicast address
|
||||
h# 00 i ne2rc!
|
||||
loop
|
||||
|
||||
h# 47 ne2-CURR ne2rc! \ Initialize CURRent pointer
|
||||
h# 22 ne2-CR ne2rc! \ Start the NIC, Abort DMA, page 0
|
||||
h# 10 ne2-GPOC ne2rc! \ Select media interface
|
||||
s" GPI = " type ne2-GPI ne2rc@ hex2 cr
|
||||
h# 00 ne2-TCR ne2rc! \ Transmitter full duplex
|
||||
h# 04 ne2-RCR ne2rc! \ Enable receiver and set accept broadcast
|
||||
else
|
||||
h# 21 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 0
|
||||
sleep.1
|
||||
|
||||
h# 00 ne2-DCR ne2rc! \ Selects word-wide DMA transfers
|
||||
h# 00 ne2-RBCR0 ne2rc! \ Load data byte count for remote DMA
|
||||
h# 00 ne2-RBCR1 ne2rc!
|
||||
|
||||
h# 20 ne2-RCR ne2rc! \ Temporarily set receiver to monitor mode
|
||||
h# 02 ne2-TCR ne2rc! \ Transmitter set to internal loopback mode
|
||||
|
||||
h# 40 ne2-TPSR ne2rc! \ Set Tx start page
|
||||
\ Initialize Receive Buffer Ring: Boundary Pointer
|
||||
\ (BNDRY), Page Start (PSTART), and Page Stop
|
||||
\ (PSTOP)
|
||||
h# 46 ne2-PSTART ne2rc!
|
||||
h# 46 ne2-BNRY ne2rc!
|
||||
h# 80 ne2-PSTOP ne2rc!
|
||||
h# ff ne2-ISR ne2rc! \ Clear Interrupt Status Register (ISR) by writing 0FFh to it.
|
||||
h# 01 ne2-IMR ne2rc! \ Initialize interrupt mask
|
||||
|
||||
h# 61 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 1
|
||||
sleep.1
|
||||
h# 12 d# 1 ne2rc! \ Set Physical Address
|
||||
h# 34 d# 2 ne2rc!
|
||||
h# 56 d# 3 ne2rc!
|
||||
h# 77 d# 4 ne2rc!
|
||||
h# 77 d# 5 ne2rc!
|
||||
h# 77 d# 6 ne2rc!
|
||||
d# 16 d# 8 do \ Set multicast address
|
||||
h# ff i ne2rc!
|
||||
loop
|
||||
|
||||
h# 47 ne2-CURR ne2rc! \ Initialize CURRent pointer
|
||||
|
||||
h# 20 ne2-CR ne2rc! \ DMA abort, page 0
|
||||
|
||||
h# 10 ne2-GPOC ne2rc! \ Select media interface
|
||||
s" GPI = " type ne2-GPI ne2rc@ hex2 cr
|
||||
h# 1c ne2-RCR ne2rc! \ Enable receiver and set accept broadcast
|
||||
h# 00 ne2-TCR ne2rc! \ Transmitter full duplex
|
||||
|
||||
h# ff ne2-ISR ne2rc! \ Clear Interrupt Status Register (ISR) by writing 0FFh to it.
|
||||
h# 22 ne2-CR ne2rc! \ Start the NIC, Abort DMA, page 0
|
||||
then
|
||||
;
|
||||
|
||||
: NicCompleteDma
|
||||
h# 22 ne2-CR ne2rc! \ Complete remote DMA
|
||||
;
|
||||
|
||||
: maca ( a -- ) \ set DMA address a
|
||||
dup d# 8 rshift ne2-RSAR1 ne2rc! ne2-RSAR0 ne2rc! ;
|
||||
: mac1b \ set DMA transfer for 1 byte
|
||||
h# 01 ne2-RBCR0 ne2rc!
|
||||
h# 00 ne2-RBCR1 ne2rc! ;
|
||||
: mac2b \ set DMA transfer for 2 bytes
|
||||
h# 02 ne2-RBCR0 ne2rc!
|
||||
h# 00 ne2-RBCR1 ne2rc! ;
|
||||
: macc@ ( a -- u )
|
||||
maca mac1b
|
||||
h# 0a ne2-CR ne2rc! \ running, DMA read
|
||||
ne2-RDMAPORT ne2rc@
|
||||
NicCompleteDma ;
|
||||
: macc! ( u a -- )
|
||||
maca mac1b
|
||||
h# 12 ne2-CR ne2rc! \ running, DMA write
|
||||
ne2-RDMAPORT ne2rc! ;
|
||||
: mac@ ( a -- u )
|
||||
maca mac2b
|
||||
h# 0a ne2-CR ne2rc! \ running, DMA read
|
||||
ne2-RDMAPORT ne2rc@ d# 8 lshift ne2-RDMAPORT ne2rc@ or
|
||||
NicCompleteDma ;
|
||||
: mac! ( u a -- )
|
||||
maca mac2b
|
||||
h# 12 ne2-CR ne2rc! \ running, DMA write
|
||||
dup d# 8 rshift ne2-RDMAPORT ne2rc! ne2-RDMAPORT ne2rc! ;
|
||||
|
||||
: mac-dump ( a u -- )
|
||||
bounds
|
||||
begin
|
||||
2dup u>
|
||||
while
|
||||
dup h# f and 0= if
|
||||
cr dup hex4 [char] : emit space
|
||||
then
|
||||
dup mac@ hex4 space
|
||||
2+
|
||||
repeat 2drop cr ;
|
||||
|
||||
variable currpkt
|
||||
|
||||
: mac-inoffset ( u -- u ) \ compute offset into current incoming packet
|
||||
currpkt @ +
|
||||
dup 0< if
|
||||
h# 8000 -
|
||||
h# 4600 +
|
||||
then
|
||||
;
|
||||
|
||||
: mac@n ( n addr -- d0 .. dn )
|
||||
swap 0do dup mac@ swap 2+ loop drop ;
|
||||
|
||||
|
||||
( words for constructing packet data JCB 07:01 08/20/10)
|
||||
variable writer
|
||||
|
||||
: mac-pkt-begin h# 4000 writer ! ;
|
||||
: bump ( n -- ) writer +! ;
|
||||
: mac-pkt-c, ( n -- ) writer @ macc! d# 1 bump ;
|
||||
: mac-pkt-, ( n -- ) writer @ mac! d# 2 bump ;
|
||||
: mac-pkt-d, ( d -- ) mac-pkt-, mac-pkt-, ;
|
||||
: mac-pkt-2, ( n0 n1 -- ) swap mac-pkt-, mac-pkt-, ;
|
||||
: mac-pkt-3, rot mac-pkt-, mac-pkt-2, ;
|
||||
: mac-pkt-,0 ( n -- ) 0do d# 0 mac-pkt-, loop ;
|
||||
: mac-pkt-s, ( caddr u -- )
|
||||
0do
|
||||
dup c@
|
||||
mac-pkt-c,
|
||||
1+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
: mac-pkt-src ( n offset -- ) \ copy n words from incoming+offset
|
||||
swap 0do
|
||||
dup mac-inoffset mac@ mac-pkt-,
|
||||
2+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
: mac-pkt-complete ( -- length ) \ set up size
|
||||
writer @ h# 4000 -
|
||||
\ h# 4000 over mac-dump
|
||||
dup ne2-TBCR0 ne2r! ;
|
||||
|
||||
: mac-checksum ( addr nwords -- sum )
|
||||
d# 0 swap
|
||||
0do
|
||||
over mac@ ( addr sum v )
|
||||
+1c
|
||||
swap 2+ swap
|
||||
loop
|
||||
nip
|
||||
invert
|
||||
;
|
||||
|
||||
: mac-snap
|
||||
s" CR PSTART PSTOP BNRY TSR NCR CPR ISR CRDA0 CRDA1 - - RSR CNTR0 CNTR1 CNTR2" type cr
|
||||
d# 16 0do
|
||||
i ne2rc@ hex2 d# 5 spaces
|
||||
loop
|
||||
;
|
||||
|
||||
: mac-fullness ( -- f )
|
||||
ether_irq @ if
|
||||
ne2-BNRY ne2rc@ 1+ ne2-CPR ne2rc@ <> dup if
|
||||
\ mac-snap
|
||||
ne2-BNRY ne2rc@ 1+ d# 8 lshift d# 4 + currpkt !
|
||||
\ s" currpkt=" type currpkt @ hex4 space
|
||||
\ currpkt @ d# 4 - macc@ hex2
|
||||
\ cr
|
||||
\ currpkt @ d# 4 - d# 16 mac-dump
|
||||
else
|
||||
ne2-clrisr
|
||||
then
|
||||
else
|
||||
false
|
||||
then
|
||||
;
|
||||
|
||||
: mac-consume ( -- ) \ finished with current packet, move on
|
||||
ne2-BNRY ne2rc@ 1+ d# 8 lshift 1+ macc@ \ next pkt
|
||||
1- ne2-BNRY ne2rc!
|
||||
;
|
||||
|
||||
variable ne2cold
|
||||
|
||||
: mac-send
|
||||
ne2cold @ 0= if
|
||||
h# 21 ne2-CR ne2rc!
|
||||
h# 22 ne2-CR ne2rc!
|
||||
true ne2cold !
|
||||
then
|
||||
|
||||
h# 40 ne2-TPSR ne2rc!
|
||||
h# 26 ne2-CR ne2rc! \ START
|
||||
;
|
||||
|
||||
: packetout-off \ compute offset in output packet
|
||||
h# 4000 + ;
|
||||
|
||||
: nicwork
|
||||
|
||||
\ ISA mode
|
||||
|
||||
\ begin
|
||||
s" TR= " type h# 15 ne2rc@ hex2 space
|
||||
s" ether_irq=" type ether_irq @ hex1 space
|
||||
s" ISR=" type ne2-ISR ne2rc@ hex2 space
|
||||
cr
|
||||
\ again
|
||||
|
||||
false if
|
||||
h# 0000 ne2-RSAR0 ne2r!
|
||||
cr
|
||||
d# 16 0do
|
||||
ne2-RDMAPORT ne2rc@ hex2 space
|
||||
loop
|
||||
cr
|
||||
then
|
||||
|
||||
s" CR PSTART PSTOP BNRY TSR NCR CPR ISR CRDA0 CRDA1 - - RSR CNTR0 CNTR1 CNTR2" type cr
|
||||
begin
|
||||
d# 16 0do
|
||||
i ne2rc@ hex2 d# 5 spaces
|
||||
loop
|
||||
ether_irq @ hex1
|
||||
cr
|
||||
sleep1
|
||||
ne2-CPR ne2rc@ h# 47 <>
|
||||
until
|
||||
|
||||
\ h# 4700 h# 100 mac-dump
|
||||
\ cr
|
||||
\ h# 0947 h# 4700 mac!
|
||||
\ h# 4700 h# 100 mac-dump
|
||||
;
|
||||
BIN
j1/firmware/font8x8
Normal file
BIN
j1/firmware/font8x8
Normal file
Binary file not shown.
BIN
j1/firmware/fsm-32.png
Normal file
BIN
j1/firmware/fsm-32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
11
j1/firmware/genoffsets.py
Normal file
11
j1/firmware/genoffsets.py
Normal file
@ -0,0 +1,11 @@
|
||||
from defines_tcpip import offsets
|
||||
|
||||
d = open("defines_tcpip.fs", "w")
|
||||
for nm,o in sorted(offsets.items()):
|
||||
print >>d, "%d constant %s" % (o, nm)
|
||||
|
||||
import defines_tcpip2
|
||||
|
||||
d = open("defines_tcpip2.fs", "w")
|
||||
for nm,o in sorted(defines_tcpip2.offsets.items()):
|
||||
print >>d, "%d constant %s" % (o, nm)
|
||||
16
j1/firmware/go
Normal file
16
j1/firmware/go
Normal file
@ -0,0 +1,16 @@
|
||||
# make doc
|
||||
# python encode.py j1.png
|
||||
# python mkblob.py ; exit
|
||||
make j1.bin || exit
|
||||
|
||||
# for ADDR in 0 80000 100000 180000
|
||||
# do
|
||||
# (. /opt/Xilinx/11.1/ISE/settings32.sh ; promgen -u $ADDR j1_program.bit -p mcs -w -o j1_program_$ADDR.mcs )
|
||||
# done
|
||||
# ./boot
|
||||
# ping -c 4 192.168.0.99 && python twist.py
|
||||
|
||||
python twist.py
|
||||
|
||||
(. /opt/Xilinx/11.1/ISE/settings32.sh ; data2mem -bm ../synth/j1_bd.bmm -bd j1.mem tag jram -bt ../synth/j1.bit -o b j1_program.bit )
|
||||
scp j1_program.bit leonard:.
|
||||
57
j1/firmware/hwdefs.fs
Normal file
57
j1/firmware/hwdefs.fs
Normal file
@ -0,0 +1,57 @@
|
||||
h# 4100 constant flash_ddir
|
||||
h# 4102 constant flash_ce_n
|
||||
h# 4104 constant flash_oe_n
|
||||
h# 4106 constant flash_we_n
|
||||
h# 4108 constant flash_byte_n
|
||||
h# 410a constant flash_rdy
|
||||
h# 410c constant flash_rst_n
|
||||
h# 410e constant flash_a
|
||||
h# 4110 constant flash_a_hi
|
||||
h# 4112 constant flash_d
|
||||
|
||||
h# 4200 constant ps2_clk
|
||||
h# 4202 constant ps2_dat
|
||||
h# 4204 constant ps2_clk_dir
|
||||
h# 4206 constant ps2_dat_dir
|
||||
h# 4208 constant kbfifocount
|
||||
h# 4210 constant kbfifo
|
||||
|
||||
h# 4300 constant vga_scroll
|
||||
h# 4302 constant vga_spritea
|
||||
h# 4304 constant vga_spriteport
|
||||
h# 4306 constant vga_line
|
||||
h# 4308 constant vga_addsprites
|
||||
|
||||
h# 4400 constant vga_spritex
|
||||
h# 4402 constant vga_spritey
|
||||
|
||||
h# 4420 constant vga_spritec
|
||||
h# 4430 constant vga_spritep
|
||||
|
||||
h# 4500 constant sw2_n
|
||||
h# 4502 constant sw3_n
|
||||
|
||||
h# 5000 constant RS232_TXD
|
||||
h# 5001 constant RESET_TRIGGER
|
||||
h# 5100 constant ether_cs_n
|
||||
h# 5101 constant ether_aen
|
||||
h# 5102 constant ether_bhe_n
|
||||
h# 5103 constant pb_a
|
||||
h# 5104 constant ddir
|
||||
h# 5105 constant pb_d
|
||||
h# 5106 constant pb_rd_n
|
||||
h# 5107 constant pb_wr_n
|
||||
h# 5108 constant ether_rdy
|
||||
h# 5109 constant ether_irq
|
||||
h# 510a constant pb_a_dir
|
||||
|
||||
h# 6000 constant time
|
||||
h# 6100 constant mult_a
|
||||
h# 6102 constant mult_b
|
||||
h# 6104 constant mult_p
|
||||
|
||||
\ Pushbuttons
|
||||
|
||||
h# 1 constant pb2
|
||||
h# 2 constant pb3
|
||||
h# 4 constant pb4
|
||||
643
j1/firmware/intelhex.py
Normal file
643
j1/firmware/intelhex.py
Normal file
@ -0,0 +1,643 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c) 2005-2007, Alexander Belchenko
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms,
|
||||
# with or without modification, are permitted provided
|
||||
# that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain
|
||||
# the above copyright notice, this list of conditions
|
||||
# and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce
|
||||
# the above copyright notice, this list of conditions
|
||||
# and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <Alexander Belchenko>
|
||||
# nor the names of its contributors may be used to endorse
|
||||
# or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''Intel HEX file format reader and converter.
|
||||
|
||||
This script also may be used as hex2bin convertor utility.
|
||||
|
||||
@author Alexander Belchenko (bialix AT ukr net)
|
||||
@version 0.8.6
|
||||
@date 2007/04/26
|
||||
'''
|
||||
|
||||
|
||||
__docformat__ = "javadoc"
|
||||
|
||||
|
||||
from array import array
|
||||
from binascii import hexlify, unhexlify
|
||||
|
||||
|
||||
class IntelHex:
|
||||
''' Intel HEX file reader. '''
|
||||
|
||||
def __init__(self, fname):
|
||||
''' Constructor.
|
||||
@param fname file name of HEX file or file object.
|
||||
'''
|
||||
#public members
|
||||
self.Error = None
|
||||
self.AddrOverlap = None
|
||||
self.padding = 0x0FF
|
||||
# Start Address
|
||||
self.start_addr = None
|
||||
|
||||
# private members
|
||||
self._fname = fname
|
||||
self._buf = {}
|
||||
self._readed = False
|
||||
self._eof = False
|
||||
self._offset = 0
|
||||
|
||||
def readfile(self):
|
||||
''' Read file into internal buffer.
|
||||
@return True if successful.
|
||||
'''
|
||||
if self._readed:
|
||||
return True
|
||||
|
||||
if not hasattr(self._fname, "read"):
|
||||
f = file(self._fname, "rU")
|
||||
fclose = f.close
|
||||
else:
|
||||
f = self._fname
|
||||
fclose = None
|
||||
|
||||
self._offset = 0
|
||||
self._eof = False
|
||||
|
||||
result = True
|
||||
|
||||
for s in f:
|
||||
if not self.decode_record(s):
|
||||
result = False
|
||||
break
|
||||
|
||||
if self._eof:
|
||||
break
|
||||
|
||||
if fclose:
|
||||
fclose()
|
||||
|
||||
self._readed = result
|
||||
return result
|
||||
|
||||
def decode_record(self, s):
|
||||
''' Decode one record of HEX file.
|
||||
@param s line with HEX record.
|
||||
@return True if line decode OK, or this is not HEX line.
|
||||
False if this is invalid HEX line or checksum error.
|
||||
'''
|
||||
s = s.rstrip('\r\n')
|
||||
if not s:
|
||||
return True # empty line
|
||||
|
||||
if s[0] == ':':
|
||||
try:
|
||||
bin = array('B', unhexlify(s[1:]))
|
||||
except TypeError:
|
||||
# this might be raised by unhexlify when odd hexascii digits
|
||||
self.Error = "Odd hexascii digits"
|
||||
return False
|
||||
length = len(bin)
|
||||
if length < 5:
|
||||
self.Error = "Too short line"
|
||||
return False
|
||||
else:
|
||||
return True # first char must be ':'
|
||||
|
||||
record_length = bin[0]
|
||||
|
||||
if length != (5 + record_length):
|
||||
self.Error = "Invalid line length"
|
||||
return False
|
||||
|
||||
addr = bin[1]*256 + bin[2]
|
||||
|
||||
record_type = bin[3]
|
||||
if not (0 <= record_type <= 5):
|
||||
self.Error = "Invalid type of record: %d" % record_type
|
||||
return False
|
||||
|
||||
crc = sum(bin)
|
||||
crc &= 0x0FF
|
||||
if crc != 0:
|
||||
self.Error = "Invalid crc"
|
||||
return False
|
||||
|
||||
if record_type == 0:
|
||||
# data record
|
||||
addr += self._offset
|
||||
for i in xrange(4, 4+record_length):
|
||||
if not self._buf.get(addr, None) is None:
|
||||
self.AddrOverlap = addr
|
||||
self._buf[addr] = bin[i]
|
||||
addr += 1 # FIXME: addr should be wrapped on 64K boundary
|
||||
|
||||
elif record_type == 1:
|
||||
# end of file record
|
||||
if record_length != 0:
|
||||
self.Error = "Bad End-of-File Record"
|
||||
return False
|
||||
self._eof = True
|
||||
|
||||
elif record_type == 2:
|
||||
# Extended 8086 Segment Record
|
||||
if record_length != 2 or addr != 0:
|
||||
self.Error = "Bad Extended 8086 Segment Record"
|
||||
return False
|
||||
self._offset = (bin[4]*256 + bin[5]) * 16
|
||||
|
||||
elif record_type == 4:
|
||||
# Extended Linear Address Record
|
||||
if record_length != 2 or addr != 0:
|
||||
self.Error = "Bad Extended Linear Address Record"
|
||||
return False
|
||||
self._offset = (bin[4]*256 + bin[5]) * 65536
|
||||
|
||||
elif record_type == 3:
|
||||
# Start Segment Address Record
|
||||
if record_length != 4 or addr != 0:
|
||||
self.Error = "Bad Start Segment Address Record"
|
||||
return False
|
||||
if self.start_addr:
|
||||
self.Error = "Start Address Record appears twice"
|
||||
return False
|
||||
self.start_addr = {'CS': bin[4]*256 + bin[5],
|
||||
'IP': bin[6]*256 + bin[7],
|
||||
}
|
||||
|
||||
elif record_type == 5:
|
||||
# Start Linear Address Record
|
||||
if record_length != 4 or addr != 0:
|
||||
self.Error = "Bad Start Linear Address Record"
|
||||
return False
|
||||
if self.start_addr:
|
||||
self.Error = "Start Address Record appears twice"
|
||||
return False
|
||||
self.start_addr = {'EIP': (bin[4]*16777216 +
|
||||
bin[5]*65536 +
|
||||
bin[6]*256 +
|
||||
bin[7]),
|
||||
}
|
||||
|
||||
return True
|
||||
|
||||
def _get_start_end(self, start=None, end=None):
|
||||
"""Return default values for start and end if they are None
|
||||
"""
|
||||
if start is None:
|
||||
start = min(self._buf.keys())
|
||||
if end is None:
|
||||
end = max(self._buf.keys())
|
||||
if start > end:
|
||||
start, end = end, start
|
||||
return start, end
|
||||
|
||||
def tobinarray(self, start=None, end=None, pad=None):
|
||||
''' Convert to binary form.
|
||||
@param start start address of output bytes.
|
||||
@param end end address of output bytes.
|
||||
@param pad fill empty spaces with this value
|
||||
(if None used self.padding).
|
||||
@return array of unsigned char data.
|
||||
'''
|
||||
if pad is None:
|
||||
pad = self.padding
|
||||
|
||||
bin = array('B')
|
||||
|
||||
if self._buf == {}:
|
||||
return bin
|
||||
|
||||
start, end = self._get_start_end(start, end)
|
||||
|
||||
for i in xrange(start, end+1):
|
||||
bin.append(self._buf.get(i, pad))
|
||||
|
||||
return bin
|
||||
|
||||
def tobinstr(self, start=None, end=None, pad=0xFF):
|
||||
''' Convert to binary form.
|
||||
@param start start address of output bytes.
|
||||
@param end end address of output bytes.
|
||||
@param pad fill empty spaces with this value
|
||||
(if None used self.padding).
|
||||
@return string of binary data.
|
||||
'''
|
||||
return self.tobinarray(start, end, pad).tostring()
|
||||
|
||||
def tobinfile(self, fobj, start=None, end=None, pad=0xFF):
|
||||
'''Convert to binary and write to file.
|
||||
|
||||
@param fobj file name or file object for writing output bytes.
|
||||
@param start start address of output bytes.
|
||||
@param end end address of output bytes.
|
||||
@param pad fill empty spaces with this value
|
||||
(if None used self.padding).
|
||||
'''
|
||||
if not hasattr(fobj, "write"):
|
||||
fobj = file(fobj, "wb")
|
||||
fclose = fobj.close
|
||||
else:
|
||||
fclose = None
|
||||
|
||||
fobj.write(self.tobinstr(start, end, pad))
|
||||
|
||||
if fclose:
|
||||
fclose()
|
||||
|
||||
def minaddr(self):
|
||||
''' Get minimal address of HEX content. '''
|
||||
aa = self._buf.keys()
|
||||
if aa == []:
|
||||
return 0
|
||||
else:
|
||||
return min(aa)
|
||||
|
||||
def maxaddr(self):
|
||||
''' Get maximal address of HEX content. '''
|
||||
aa = self._buf.keys()
|
||||
if aa == []:
|
||||
return 0
|
||||
else:
|
||||
return max(aa)
|
||||
|
||||
def __getitem__(self, addr):
|
||||
''' Get byte from address.
|
||||
@param addr address of byte.
|
||||
@return byte if address exists in HEX file, or self.padding
|
||||
if no data found.
|
||||
'''
|
||||
return self._buf.get(addr, self.padding)
|
||||
|
||||
def __setitem__(self, addr, byte):
|
||||
self._buf[addr] = byte
|
||||
|
||||
def writefile(self, f, write_start_addr=True):
|
||||
"""Write data to file f in HEX format.
|
||||
|
||||
@param f filename or file-like object for writing
|
||||
@param write_start_addr enable or disable writing start address
|
||||
record to file (enabled by default).
|
||||
If there is no start address nothing
|
||||
will be written.
|
||||
|
||||
@return True if successful.
|
||||
"""
|
||||
fwrite = getattr(f, "write", None)
|
||||
if fwrite:
|
||||
fobj = f
|
||||
fclose = None
|
||||
else:
|
||||
fobj = file(f, 'w')
|
||||
fwrite = fobj.write
|
||||
fclose = fobj.close
|
||||
|
||||
# start address record if any
|
||||
if self.start_addr and write_start_addr:
|
||||
keys = self.start_addr.keys()
|
||||
keys.sort()
|
||||
bin = array('B', '\0'*9)
|
||||
if keys == ['CS','IP']:
|
||||
# Start Segment Address Record
|
||||
bin[0] = 4 # reclen
|
||||
bin[1] = 0 # offset msb
|
||||
bin[2] = 0 # offset lsb
|
||||
bin[3] = 3 # rectyp
|
||||
cs = self.start_addr['CS']
|
||||
bin[4] = (cs >> 8) & 0x0FF
|
||||
bin[5] = cs & 0x0FF
|
||||
ip = self.start_addr['IP']
|
||||
bin[6] = (ip >> 8) & 0x0FF
|
||||
bin[7] = ip & 0x0FF
|
||||
bin[8] = (-sum(bin)) & 0x0FF # chksum
|
||||
fwrite(':')
|
||||
fwrite(hexlify(bin.tostring()).upper())
|
||||
fwrite('\n')
|
||||
elif keys == ['EIP']:
|
||||
# Start Linear Address Record
|
||||
bin[0] = 4 # reclen
|
||||
bin[1] = 0 # offset msb
|
||||
bin[2] = 0 # offset lsb
|
||||
bin[3] = 5 # rectyp
|
||||
eip = self.start_addr['EIP']
|
||||
bin[4] = (eip >> 24) & 0x0FF
|
||||
bin[5] = (eip >> 16) & 0x0FF
|
||||
bin[6] = (eip >> 8) & 0x0FF
|
||||
bin[7] = eip & 0x0FF
|
||||
bin[8] = (-sum(bin)) & 0x0FF # chksum
|
||||
fwrite(':')
|
||||
fwrite(hexlify(bin.tostring()).upper())
|
||||
fwrite('\n')
|
||||
else:
|
||||
self.Error = ('Invalid start address value: %r'
|
||||
% self.start_addr)
|
||||
return False
|
||||
|
||||
# data
|
||||
minaddr = IntelHex.minaddr(self)
|
||||
maxaddr = IntelHex.maxaddr(self)
|
||||
if maxaddr > 65535:
|
||||
offset = (minaddr/65536)*65536
|
||||
else:
|
||||
offset = None
|
||||
|
||||
while True:
|
||||
if offset != None:
|
||||
# emit 32-bit offset record
|
||||
high_ofs = offset / 65536
|
||||
offset_record = ":02000004%04X" % high_ofs
|
||||
bytes = divmod(high_ofs, 256)
|
||||
csum = 2 + 4 + bytes[0] + bytes[1]
|
||||
csum = (-csum) & 0x0FF
|
||||
offset_record += "%02X\n" % csum
|
||||
|
||||
ofs = offset
|
||||
if (ofs + 65536) > maxaddr:
|
||||
rng = xrange(maxaddr - ofs + 1)
|
||||
else:
|
||||
rng = xrange(65536)
|
||||
else:
|
||||
ofs = 0
|
||||
offset_record = ''
|
||||
rng = xrange(maxaddr + 1)
|
||||
|
||||
csum = 0
|
||||
k = 0
|
||||
record = ""
|
||||
for addr in rng:
|
||||
byte = self._buf.get(ofs+addr, None)
|
||||
if byte != None:
|
||||
if k == 0:
|
||||
# optionally offset record
|
||||
fobj.write(offset_record)
|
||||
offset_record = ''
|
||||
# start data record
|
||||
record += "%04X00" % addr
|
||||
bytes = divmod(addr, 256)
|
||||
csum = bytes[0] + bytes[1]
|
||||
|
||||
k += 1
|
||||
# continue data in record
|
||||
record += "%02X" % byte
|
||||
csum += byte
|
||||
|
||||
# check for length of record
|
||||
if k < 16:
|
||||
continue
|
||||
|
||||
if k != 0:
|
||||
# close record
|
||||
csum += k
|
||||
csum = (-csum) & 0x0FF
|
||||
record += "%02X" % csum
|
||||
fobj.write(":%02X%s\n" % (k, record))
|
||||
# cleanup
|
||||
csum = 0
|
||||
k = 0
|
||||
record = ""
|
||||
else:
|
||||
if k != 0:
|
||||
# close record
|
||||
csum += k
|
||||
csum = (-csum) & 0x0FF
|
||||
record += "%02X" % csum
|
||||
fobj.write(":%02X%s\n" % (k, record))
|
||||
|
||||
# advance offset
|
||||
if offset is None:
|
||||
break
|
||||
|
||||
offset += 65536
|
||||
if offset > maxaddr:
|
||||
break
|
||||
|
||||
# end-of-file record
|
||||
fobj.write(":00000001FF\n")
|
||||
if fclose:
|
||||
fclose()
|
||||
|
||||
return True
|
||||
#/IntelHex
|
||||
|
||||
|
||||
class IntelHex16bit(IntelHex):
|
||||
"""Access to data as 16-bit words."""
|
||||
|
||||
def __init__(self, source):
|
||||
"""Construct class from HEX file
|
||||
or from instance of ordinary IntelHex class.
|
||||
|
||||
@param source file name of HEX file or file object
|
||||
or instance of ordinary IntelHex class
|
||||
"""
|
||||
if isinstance(source, IntelHex):
|
||||
# from ihex8
|
||||
self.Error = source.Error
|
||||
self.AddrOverlap = source.AddrOverlap
|
||||
self.padding = source.padding
|
||||
|
||||
# private members
|
||||
self._fname = source._fname
|
||||
self._buf = source._buf
|
||||
self._readed = source._readed
|
||||
self._eof = source._eof
|
||||
self._offset = source._offset
|
||||
else:
|
||||
IntelHex.__init__(self, source)
|
||||
|
||||
if self.padding == 0x0FF:
|
||||
self.padding = 0x0FFFF
|
||||
|
||||
def __getitem__(self, addr16):
|
||||
"""Get 16-bit word from address.
|
||||
Raise error if found only one byte from pair.
|
||||
|
||||
@param addr16 address of word (addr8 = 2 * addr16).
|
||||
@return word if bytes exists in HEX file, or self.padding
|
||||
if no data found.
|
||||
"""
|
||||
addr1 = addr16 * 2
|
||||
addr2 = addr1 + 1
|
||||
byte1 = self._buf.get(addr1, None)
|
||||
byte2 = self._buf.get(addr2, None)
|
||||
|
||||
if byte1 != None and byte2 != None:
|
||||
return byte1 | (byte2 << 8) # low endian
|
||||
|
||||
if byte1 == None and byte2 == None:
|
||||
return self.padding
|
||||
|
||||
raise Exception, 'Bad access in 16-bit mode (not enough data)'
|
||||
|
||||
def __setitem__(self, addr16, word):
|
||||
addr_byte = addr16 * 2
|
||||
bytes = divmod(word, 256)
|
||||
self._buf[addr_byte] = bytes[1]
|
||||
self._buf[addr_byte+1] = bytes[0]
|
||||
|
||||
def minaddr(self):
|
||||
'''Get minimal address of HEX content in 16-bit mode.'''
|
||||
aa = self._buf.keys()
|
||||
if aa == []:
|
||||
return 0
|
||||
else:
|
||||
return min(aa)/2
|
||||
|
||||
def maxaddr(self):
|
||||
'''Get maximal address of HEX content in 16-bit mode.'''
|
||||
aa = self._buf.keys()
|
||||
if aa == []:
|
||||
return 0
|
||||
else:
|
||||
return max(aa)/2
|
||||
|
||||
#/class IntelHex16bit
|
||||
|
||||
|
||||
def hex2bin(fin, fout, start=None, end=None, size=None, pad=0xFF):
|
||||
"""Hex-to-Bin convertor engine.
|
||||
@return 0 if all OK
|
||||
|
||||
@param fin input hex file (filename or file-like object)
|
||||
@param fout output bin file (filename or file-like object)
|
||||
@param start start of address range (optional)
|
||||
@param end end of address range (optional)
|
||||
@param size size of resulting file (in bytes) (optional)
|
||||
@param pad padding byte (optional)
|
||||
"""
|
||||
h = IntelHex(fin)
|
||||
if not h.readfile():
|
||||
print "Bad HEX file"
|
||||
return 1
|
||||
|
||||
# start, end, size
|
||||
if size != None and size != 0:
|
||||
if end == None:
|
||||
if start == None:
|
||||
start = h.minaddr()
|
||||
end = start + size - 1
|
||||
else:
|
||||
if (end+1) >= size:
|
||||
start = end + 1 - size
|
||||
else:
|
||||
start = 0
|
||||
|
||||
try:
|
||||
h.tobinfile(fout, start, end, pad)
|
||||
except IOError:
|
||||
print "Could not write to file: %s" % fout
|
||||
return 1
|
||||
|
||||
return 0
|
||||
#/def hex2bin
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import getopt
|
||||
import os
|
||||
import sys
|
||||
|
||||
usage = '''Hex2Bin python converting utility.
|
||||
Usage:
|
||||
python intelhex.py [options] file.hex [out.bin]
|
||||
|
||||
Arguments:
|
||||
file.hex name of hex file to processing.
|
||||
out.bin name of output file.
|
||||
If omitted then output write to file.bin.
|
||||
|
||||
Options:
|
||||
-h, --help this help message.
|
||||
-p, --pad=FF pad byte for empty spaces (ascii hex value).
|
||||
-r, --range=START:END specify address range for writing output
|
||||
(ascii hex value).
|
||||
Range can be in form 'START:' or ':END'.
|
||||
-l, --length=NNNN,
|
||||
-s, --size=NNNN size of output (decimal value).
|
||||
'''
|
||||
|
||||
pad = 0xFF
|
||||
start = None
|
||||
end = None
|
||||
size = None
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hp:r:l:s:",
|
||||
["help", "pad=", "range=",
|
||||
"length=", "size="])
|
||||
|
||||
for o, a in opts:
|
||||
if o in ("-h", "--help"):
|
||||
print usage
|
||||
sys.exit(0)
|
||||
elif o in ("-p", "--pad"):
|
||||
try:
|
||||
pad = int(a, 16) & 0x0FF
|
||||
except:
|
||||
raise getopt.GetoptError, 'Bad pad value'
|
||||
elif o in ("-r", "--range"):
|
||||
try:
|
||||
l = a.split(":")
|
||||
if l[0] != '':
|
||||
start = int(l[0], 16)
|
||||
if l[1] != '':
|
||||
end = int(l[1], 16)
|
||||
except:
|
||||
raise getopt.GetoptError, 'Bad range value(s)'
|
||||
elif o in ("-l", "--lenght", "-s", "--size"):
|
||||
try:
|
||||
size = int(a, 10)
|
||||
except:
|
||||
raise getopt.GetoptError, 'Bad size value'
|
||||
|
||||
if start != None and end != None and size != None:
|
||||
raise getopt.GetoptError, 'Cannot specify START:END and SIZE simultaneously'
|
||||
|
||||
if not args:
|
||||
raise getopt.GetoptError, 'Hex file is not specified'
|
||||
|
||||
if len(args) > 2:
|
||||
raise getopt.GetoptError, 'Too many arguments'
|
||||
|
||||
except getopt.GetoptError, msg:
|
||||
print msg
|
||||
print usage
|
||||
sys.exit(2)
|
||||
|
||||
fin = args[0]
|
||||
if len(args) == 1:
|
||||
import os.path
|
||||
name, ext = os.path.splitext(fin)
|
||||
fout = name + ".bin"
|
||||
else:
|
||||
fout = args[1]
|
||||
|
||||
if not os.path.isfile(fin):
|
||||
print "File not found"
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(hex2bin(fin, fout, start, end, size, pad))
|
||||
362
j1/firmware/invaders.fs
Normal file
362
j1/firmware/invaders.fs
Normal file
@ -0,0 +1,362 @@
|
||||
( Space invaders JCB 10:43 11/18/10)
|
||||
|
||||
: whereis ( t -- x y )
|
||||
>r
|
||||
d# 384 r@ sin* d# 384 +
|
||||
r@ d# 4 rshift d# 32 r> 2* sin* +
|
||||
;
|
||||
|
||||
56 constant nsprites
|
||||
|
||||
nsprites array invx
|
||||
nsprites array invy
|
||||
nsprites array alive
|
||||
nsprites array invnext
|
||||
nsprites array anim
|
||||
|
||||
: invload ( i -- ) \ load sprite i
|
||||
\ s" sprite " type dup . s" at " type dup invx @ . dup invy @ . cr
|
||||
dup invx @ swap
|
||||
dup invy @ swap
|
||||
dup anim @ swap
|
||||
d# 7 and
|
||||
tuck cells vga_spritep + !
|
||||
sprite!
|
||||
;
|
||||
|
||||
: inv-makedl ( -- )
|
||||
erasedl
|
||||
nsprites 0do
|
||||
\ invy -ve load sprite; +ve gives the dl offset
|
||||
i alive @ if
|
||||
i invy @ dup 0< if
|
||||
drop i invload
|
||||
else
|
||||
dup d# 512 < if
|
||||
\ dl[y] -> invnext[i]
|
||||
\ i -> dl[y]
|
||||
cells dl + dup
|
||||
@ i invnext !
|
||||
i swap !
|
||||
else
|
||||
drop
|
||||
then
|
||||
then
|
||||
then
|
||||
loop
|
||||
;
|
||||
|
||||
: inv-chase
|
||||
d# 512 0do
|
||||
begin vga-line@ i = until
|
||||
\ s" line" type i . cr
|
||||
i cells dl + @
|
||||
begin
|
||||
dup d# 0 >=
|
||||
while
|
||||
dup invload
|
||||
invnext @
|
||||
repeat
|
||||
loop
|
||||
;
|
||||
|
||||
: born ( x y i ) \ sprite i born
|
||||
dup alive on
|
||||
tuck invy !
|
||||
invx !
|
||||
;
|
||||
|
||||
: kill ( i -- ) \ kill sprite i
|
||||
d# 512 over invy !
|
||||
alive off
|
||||
;
|
||||
|
||||
: isalien ( u -- f)
|
||||
d# 6 and d# 6 <> ;
|
||||
|
||||
: moveto ( i -- ) \ move invader i to current position
|
||||
dup d# 6 and d# 6 <>
|
||||
over alive @ and if
|
||||
>r
|
||||
frame @ r@ d# 7 and d# 8 * + whereis
|
||||
r@ d# 3 rshift d# 40 * +
|
||||
r@ invy !
|
||||
r> invx !
|
||||
else
|
||||
drop
|
||||
then
|
||||
;
|
||||
|
||||
: bomb ( u -- u ) d# 3 lshift d# 6 + ;
|
||||
: shot ( u -- u ) d# 3 lshift d# 7 + ;
|
||||
|
||||
8 array lowest
|
||||
|
||||
: findlowest
|
||||
d# 8 0do d# -1 i lowest ! loop
|
||||
d# 48 0do
|
||||
i alive @ if
|
||||
i dup d# 7 and lowest !
|
||||
then
|
||||
loop
|
||||
;
|
||||
|
||||
create bias 0 , 1 , 2 , 3 , 4 , 5 , 0 , 5 ,
|
||||
: rand6
|
||||
time @ d# 7 and cells bias + @
|
||||
;
|
||||
|
||||
2variable bombalarm
|
||||
variable nextbomb
|
||||
|
||||
2variable shotalarm
|
||||
variable nextshot
|
||||
|
||||
variable playerx
|
||||
variable lives
|
||||
2variable score
|
||||
variable dying
|
||||
|
||||
32 constant girth
|
||||
|
||||
: 1+mod6 ( a )
|
||||
dup @ dup d# 5 = if d# -5 else d# 1 then + swap ! ;
|
||||
|
||||
: .status
|
||||
'emit @ >r ['] vga-emit 'emit !
|
||||
|
||||
home
|
||||
s" LIVES " type lives @ .
|
||||
d# 38 d# 0 vga-at-xy
|
||||
s" SCORE " type score 2@ <# # # # # # # #> type
|
||||
cr
|
||||
|
||||
lives @ 0= if
|
||||
['] vga-bigemit 'emit !
|
||||
d# 8 d# 7 vga-at-xy s" GAME" type
|
||||
d# 8 d# 17 vga-at-xy s" OVER" type
|
||||
then
|
||||
|
||||
r> 'emit !
|
||||
;
|
||||
|
||||
: newlife
|
||||
d# -1 lives +! .status
|
||||
d# 0 dying !
|
||||
d# 100 playerx !
|
||||
;
|
||||
|
||||
: parabolic ( dx dy i -- ) \ move sprite i in parabolic path
|
||||
>r
|
||||
swap r@ invx +!
|
||||
dying @ d# 3 rshift +
|
||||
r> invy +!
|
||||
;
|
||||
|
||||
: exploding
|
||||
d# 3 d# -4 d# 48 parabolic
|
||||
d# -3 d# -4 d# 49 parabolic
|
||||
d# -4 d# -3 d# 50 parabolic
|
||||
d# 4 d# -3 d# 51 parabolic
|
||||
d# -5 d# -2 d# 52 parabolic
|
||||
d# 5 d# -2 d# 53 parabolic
|
||||
d# 1 d# -2 d# 55 parabolic
|
||||
;
|
||||
|
||||
: @xy ( i -- x y )
|
||||
dup invx @ swap invy @ ;
|
||||
|
||||
: dist ( u1 u2 )
|
||||
invert + dup 0< xor ;
|
||||
|
||||
: fall
|
||||
d# 6 0do
|
||||
i bomb
|
||||
d# 4 over invy +!
|
||||
@xy d# 470 dist d# 16 < swap
|
||||
playerx @ dist girth < and
|
||||
dying @ 0= and if
|
||||
d# 1 dying !
|
||||
then
|
||||
loop
|
||||
;
|
||||
|
||||
: trigger \ if shotalarm expired, launch new shot
|
||||
shotalarm isalarm if
|
||||
d# 400000. shotalarm setalarm
|
||||
playerx @ d# 480
|
||||
nextshot @ shot born
|
||||
nextshot 1+mod6
|
||||
then
|
||||
;
|
||||
|
||||
: collide ( x y -- u )
|
||||
d# 48 0do
|
||||
i isalien i alive @ and if
|
||||
over i invx @ dist d# 16 <
|
||||
over i invy @ dist d# 16 < and if
|
||||
2drop i unloop exit
|
||||
then
|
||||
then
|
||||
loop
|
||||
2drop
|
||||
d# -1
|
||||
;
|
||||
|
||||
: rise
|
||||
d# 6 0do
|
||||
i shot >r r@ alive @ if
|
||||
d# -5 r@ invy +!
|
||||
r@ invy @ d# -30 < if r@ kill then
|
||||
r@ @xy collide dup 0< if
|
||||
drop
|
||||
else
|
||||
kill r@ kill
|
||||
d# 10. score 2@ d+ score 2!
|
||||
.status
|
||||
then
|
||||
then
|
||||
r> drop
|
||||
loop
|
||||
;
|
||||
|
||||
: doplayer
|
||||
lives @ if
|
||||
dying @ 0= if
|
||||
buttons >r
|
||||
|
||||
girth 2/ playerx @ <
|
||||
r@ pb2 and and if
|
||||
d# -4 playerx +!
|
||||
then
|
||||
|
||||
playerx @ d# 800 girth 2/ - <
|
||||
r@ pb3 and and if
|
||||
d# 4 playerx +!
|
||||
then
|
||||
|
||||
r> pb4 and if
|
||||
trigger
|
||||
\ else trigger
|
||||
then
|
||||
|
||||
d# 6 0do
|
||||
frame @ d# 3 lshift i d# 42 * +
|
||||
girth swap sin* playerx @ +
|
||||
d# 480
|
||||
i d# 48 +
|
||||
dup anim on
|
||||
born
|
||||
loop
|
||||
playerx @ d# 470 d# 55 born
|
||||
else
|
||||
exploding
|
||||
d# 1 dying +!
|
||||
dying @ d# 100 > if
|
||||
newlife
|
||||
then
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
create cscheme
|
||||
h# 400 ,
|
||||
h# 440 ,
|
||||
h# 040 ,
|
||||
h# 044 ,
|
||||
h# 004 ,
|
||||
h# 404 ,
|
||||
h# 340 ,
|
||||
h# 444 ,
|
||||
|
||||
: invaders-cold
|
||||
vga-page
|
||||
d# 16384 0do
|
||||
h# 208000. 2/ i s>d d+ flash@
|
||||
i vga_spritea ! vga_spriteport !
|
||||
loop
|
||||
|
||||
vga_addsprites on
|
||||
rainbow
|
||||
|
||||
\ vga_spritep d# 6 cells + on
|
||||
|
||||
\ everything dead
|
||||
nsprites 0do
|
||||
i kill
|
||||
loop
|
||||
|
||||
\ all aliens alive
|
||||
d# 48 0do
|
||||
i isalien i alive !
|
||||
loop
|
||||
|
||||
d# 500000. bombalarm setalarm
|
||||
d# 0 nextbomb !
|
||||
d# 100000. shotalarm setalarm
|
||||
d# 0 nextshot !
|
||||
d# 4 lives !
|
||||
d# 0. score 2!
|
||||
|
||||
newlife
|
||||
|
||||
time@ xor seed !
|
||||
d# 0 frame !
|
||||
d# 48 0do i moveto loop
|
||||
;
|
||||
|
||||
0 [IF]
|
||||
: escape
|
||||
vision isalarm next? or ;
|
||||
: restart
|
||||
vision isalarm sw2_n @ 0= or ;
|
||||
[ELSE]
|
||||
: escape
|
||||
next? ;
|
||||
: restart
|
||||
sw2_n @ 0= ;
|
||||
[THEN]
|
||||
|
||||
: gameloop
|
||||
invaders-cold
|
||||
begin
|
||||
depth if snap then
|
||||
inv-makedl
|
||||
depth if snap then
|
||||
inv-chase
|
||||
depth if snap then
|
||||
frame @ 1+ frame !
|
||||
d# 48 0do i moveto loop
|
||||
findlowest
|
||||
bombalarm isalarm if
|
||||
d# 800000. bombalarm setalarm
|
||||
rand6 lowest @ dup 0< if
|
||||
drop
|
||||
else
|
||||
dup invx @ swap invy @
|
||||
dup d# 460 > if d# 1 dying ! then
|
||||
nextbomb @ bomb born
|
||||
nextbomb 1+mod6
|
||||
then
|
||||
then
|
||||
depth if snap then
|
||||
fall
|
||||
depth if snap then
|
||||
rise
|
||||
depth if snap then
|
||||
doplayer
|
||||
depth if snap then
|
||||
escape if exit then
|
||||
again
|
||||
;
|
||||
|
||||
: invaders-main
|
||||
invaders-cold
|
||||
d# 9000000. vision setalarm
|
||||
|
||||
gameloop
|
||||
snap
|
||||
|
||||
frame @ . s" frames" type cr
|
||||
;
|
||||
|
||||
124
j1/firmware/ip.fs
Normal file
124
j1/firmware/ip.fs
Normal file
@ -0,0 +1,124 @@
|
||||
( IP networking: headers and wrapup JCB 13:21 08/24/10)
|
||||
module[ ip"
|
||||
|
||||
: ip-datalength ( -- u ) \ length of current IP packet in words
|
||||
ETH.IP.LENGTH packet@
|
||||
d# 20 - 2/
|
||||
;
|
||||
|
||||
: ip-isproto ( u -- f ) \ true if packet PROTO is u
|
||||
ETH.IP.TTLPROTO packet@ h# ff and =
|
||||
;
|
||||
|
||||
: ip-identification
|
||||
ip-id-counter d# 1 over +! @
|
||||
;
|
||||
|
||||
: @ethaddr ( eth-addr -- mac01 mac23 mac45 )
|
||||
?dup
|
||||
if
|
||||
dup @ swap 2+ 2@
|
||||
else
|
||||
ethaddr-broadcast
|
||||
then
|
||||
;
|
||||
|
||||
: ip-header ( dst-ip src-ip eth-addr protocol -- )
|
||||
>r
|
||||
mac-pkt-begin
|
||||
|
||||
@ethaddr mac-pkt-3,
|
||||
net-my-mac mac-pkt-3,
|
||||
h# 800 mac-pkt-,
|
||||
|
||||
h# 4500
|
||||
h# 0000 \ length
|
||||
ip-identification
|
||||
mac-pkt-3,
|
||||
h# 4000 \ do not fragment
|
||||
h# 4000 r> or \ TTL, protocol
|
||||
d# 0 \ checksum
|
||||
mac-pkt-3,
|
||||
mac-pkt-2, \ src ip
|
||||
mac-pkt-2, \ dst ip
|
||||
;
|
||||
|
||||
: ip-wrapup ( bytelen -- )
|
||||
\ write IP length
|
||||
ETH.IP -
|
||||
ETH.IP.LENGTH packetout-off mac!
|
||||
|
||||
\ write IP checksum
|
||||
ETH.IP packetout-off d# 10 mac-checksum
|
||||
ETH.IP.CHKSUM packetout-off mac!
|
||||
;
|
||||
|
||||
: ip-packet-srcip
|
||||
d# 2 ETH.IP.SRCIP mac-inoffset mac@n
|
||||
;
|
||||
|
||||
( ICMP return and originate JCB 13:22 08/24/10)
|
||||
|
||||
\ Someone pings us, generate a return packet
|
||||
|
||||
: icmp-handler
|
||||
IP_PROTO_ICMP ip-isproto
|
||||
ETH.IP.ICMP.TYPECODE packet@ h# 800 =
|
||||
and if
|
||||
ip-packet-srcip
|
||||
2dup arp-lookup
|
||||
?dup if
|
||||
\ transmit ICMP reply
|
||||
\ dstip *ethaddr
|
||||
net-my-ip rot \ dstip srcip *ethaddr
|
||||
d# 1 ip-header
|
||||
|
||||
\ Now the ICMP header
|
||||
d# 0 mac-pkt-,
|
||||
|
||||
s" =====> ICMP seq " type
|
||||
ETH.IP.ICMP.SEQUENCE mac-inoffset mac@ u. cr
|
||||
|
||||
ETH.IP.ICMP.IDENTIFIER mac-inoffset
|
||||
ip-datalength 2- ( offset n )
|
||||
tuck
|
||||
mac-checksum mac-pkt-,
|
||||
ETH.IP.ICMP.IDENTIFIER mac-pkt-src
|
||||
|
||||
mac-pkt-complete
|
||||
ip-wrapup
|
||||
mac-send
|
||||
else
|
||||
2drop
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
: ping ( ip. -- ) \ originate
|
||||
2dup arp-lookup
|
||||
?dup if
|
||||
\ transmit ICMP request
|
||||
\ dstip *ethaddr
|
||||
net-my-ip rot \ dstip srcip *ethaddr
|
||||
d# 1 ip-header
|
||||
|
||||
\ Now the ICMP header
|
||||
h# 800 mac-pkt-,
|
||||
|
||||
\ id is h# 550b, seq is lo word of time
|
||||
h# 550b time@ drop
|
||||
2dup +1c h# 800 +1c
|
||||
d# 28 begin swap d# 0 +1c swap 1- dup 0= until drop
|
||||
invert mac-pkt-, \ checksum
|
||||
mac-pkt-2,
|
||||
d# 28 mac-pkt-,0
|
||||
|
||||
mac-pkt-complete
|
||||
ip-wrapup
|
||||
mac-send
|
||||
else
|
||||
2drop
|
||||
then
|
||||
;
|
||||
|
||||
]module
|
||||
70
j1/firmware/ip0.fs
Normal file
70
j1/firmware/ip0.fs
Normal file
@ -0,0 +1,70 @@
|
||||
( Variables for IP networking JCB 13:21 08/24/10)
|
||||
|
||||
module[ ip0"
|
||||
create ip-id-counter d# 2 allot
|
||||
create ip-addr d# 4 allot
|
||||
create ip-router d# 4 allot
|
||||
create ip-subnetmask d# 4 allot
|
||||
create ip-dns d# 4 allot
|
||||
create icmp-alarm-ptr d# 1 allot
|
||||
|
||||
: ethaddr-broadcast
|
||||
h# ffff dup dup
|
||||
;
|
||||
|
||||
: net-my-ip
|
||||
ip-addr 2@
|
||||
;
|
||||
|
||||
: ethaddr-pretty-w
|
||||
dup endian hex2
|
||||
[char] : emit
|
||||
hex2
|
||||
;
|
||||
|
||||
: ethaddr-pretty
|
||||
swap rot
|
||||
ethaddr-pretty-w [char] : emit
|
||||
ethaddr-pretty-w [char] : emit
|
||||
ethaddr-pretty-w
|
||||
;
|
||||
|
||||
: ip-pretty-byte
|
||||
h# ff and
|
||||
\ d# 0 u.r
|
||||
hex2
|
||||
;
|
||||
|
||||
: ip-pretty-2
|
||||
dup swab ip-pretty-byte [char] . emit ip-pretty-byte
|
||||
;
|
||||
|
||||
: ip-pretty
|
||||
swap
|
||||
ip-pretty-2 [char] . emit
|
||||
ip-pretty-2
|
||||
;
|
||||
|
||||
( IP address literals JCB 14:30 10/26/10)
|
||||
|
||||
================================================================
|
||||
|
||||
It is neat to write IP address literals e.g.
|
||||
ip# 192.168.0.1
|
||||
|
||||
================================================================
|
||||
|
||||
meta
|
||||
|
||||
: octet# ( c -- u ) 0. rot parse >number throw 2drop ;
|
||||
|
||||
: ip#
|
||||
[char] . octet# 8 lshift
|
||||
[char] . octet# or do-number
|
||||
[char] . octet# 8 lshift
|
||||
bl octet# or do-number
|
||||
;
|
||||
|
||||
target
|
||||
|
||||
]module
|
||||
BIN
j1/firmware/j1.png
Normal file
BIN
j1/firmware/j1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
28
j1/firmware/keycodes.fs
Normal file
28
j1/firmware/keycodes.fs
Normal file
@ -0,0 +1,28 @@
|
||||
9 constant TAB
|
||||
10 constant ENTER
|
||||
27 constant ESC
|
||||
|
||||
h# 80 constant KDEL
|
||||
|
||||
h# 81 constant KF1
|
||||
h# 82 constant KF2
|
||||
h# 83 constant KF3
|
||||
h# 84 constant KF4
|
||||
h# 85 constant KF5
|
||||
h# 86 constant KF6
|
||||
h# 87 constant KF7
|
||||
h# 88 constant KF8
|
||||
h# 89 constant KF9
|
||||
h# 8a constant KF10
|
||||
h# 8b constant KF11
|
||||
h# 8c constant KF12
|
||||
|
||||
h# 90 constant KHOME
|
||||
h# 91 constant KPGUP
|
||||
h# 92 constant KPGDN
|
||||
h# 93 constant KEND
|
||||
h# 94 constant KLEFT
|
||||
h# 95 constant KRIGHT
|
||||
h# 96 constant KUP
|
||||
h# 97 constant KDOWN
|
||||
h# 98 constant KINS
|
||||
114
j1/firmware/loader.fs
Normal file
114
j1/firmware/loader.fs
Normal file
@ -0,0 +1,114 @@
|
||||
( LOADER PROTOCOL JCB 09:16 11/11/10)
|
||||
|
||||
947 constant PORT
|
||||
|
||||
: response0 ( -- )
|
||||
ETH.IP.UDP.SOURCEPORT packet@
|
||||
PORT
|
||||
d# 2 ETH.IP.SRCIP mac-inoffset mac@n
|
||||
net-my-ip
|
||||
2over arp-lookup
|
||||
( dst-port src-port dst-ip src-ip *ethaddr )
|
||||
udp-header
|
||||
d# 0 mac-pkt-,
|
||||
ETH.IP.UDP.LOADER.SEQNO packet@ mac-pkt-,
|
||||
;
|
||||
|
||||
: response1
|
||||
udp-wrapup mac-send
|
||||
;
|
||||
|
||||
: respond
|
||||
response0
|
||||
response1
|
||||
;
|
||||
|
||||
: ramread
|
||||
response0
|
||||
ETH.IP.UDP.LOADER.RAMREAD.ADDR packet@
|
||||
d# 128 bounds begin
|
||||
dup @ mac-pkt-,
|
||||
cell+
|
||||
2dup=
|
||||
until
|
||||
2drop
|
||||
response1
|
||||
;
|
||||
|
||||
: ramwrite
|
||||
ETH.IP.UDP.LOADER.RAMWRITE.ADDR packet@
|
||||
d# 64 0do
|
||||
ETH.IP.UDP.LOADER.RAMWRITE.DATA i cells + packet@
|
||||
over !
|
||||
cell+
|
||||
loop
|
||||
drop
|
||||
respond
|
||||
;
|
||||
|
||||
: reboot
|
||||
respond bootloader ;
|
||||
|
||||
: flashread
|
||||
response0
|
||||
ETH.IP.UDP.LOADER.FLASHREAD.ADDR packetd@ d2/
|
||||
flash-reset
|
||||
d# 64 0do
|
||||
2dup flash@
|
||||
mac-pkt-,
|
||||
d1+
|
||||
loop
|
||||
2drop
|
||||
response1
|
||||
;
|
||||
|
||||
: flasherase
|
||||
respond flash-chiperase ;
|
||||
|
||||
: flashdone
|
||||
response0
|
||||
ETH.IP.UDP.LOADER.FLASHREAD.ADDR packetd@ d2/
|
||||
flash-erased mac-pkt-,
|
||||
response1
|
||||
;
|
||||
|
||||
: flashwrite
|
||||
ETH.IP.UDP.LOADER.FLASHWRITE.ADDR packetd@ d2/
|
||||
d# 64 0do
|
||||
2dup
|
||||
ETH.IP.UDP.LOADER.FLASHWRITE.DATA i cells + packet@
|
||||
-rot flash!
|
||||
d1+
|
||||
loop
|
||||
2drop
|
||||
respond
|
||||
;
|
||||
|
||||
: flashsectorerase
|
||||
ETH.IP.UDP.LOADER.FLASHWRITE.ADDR packetd@ d2/
|
||||
flash-sectorerase
|
||||
respond
|
||||
;
|
||||
|
||||
jumptable opcodes
|
||||
( 0 ) | ramread
|
||||
( 1 ) | ramwrite
|
||||
( 2 ) | reboot
|
||||
( 3 ) | flashread
|
||||
( 4 ) | flasherase
|
||||
( 5 ) | flashdone
|
||||
( 6 ) | flashwrite
|
||||
( 7 ) | flashsectorerase
|
||||
|
||||
: loader-handler ( -- )
|
||||
IP_PROTO_UDP ip-isproto if
|
||||
ETH.IP.UDP.DESTPORT packet@ PORT =
|
||||
d# 2 ETH.IP.SRCIP mac-inoffset mac@n arp-lookup 0<> and if
|
||||
udp-checksum? if
|
||||
ETH.IP.UDP.LOADER.OPCODE packet@
|
||||
\ s" loader opcode=" type dup hex4 cr
|
||||
opcodes execute
|
||||
then
|
||||
then
|
||||
then
|
||||
;
|
||||
799
j1/firmware/main.fs
Normal file
799
j1/firmware/main.fs
Normal file
@ -0,0 +1,799 @@
|
||||
( Main for WGE firmware JCB 13:24 08/24/10)
|
||||
|
||||
\ warnings off
|
||||
\ require tags.fs
|
||||
|
||||
include crossj1.fs
|
||||
meta
|
||||
: TARGET? 1 ;
|
||||
: build-debug? 1 ;
|
||||
|
||||
include basewords.fs
|
||||
target
|
||||
include hwdefs.fs
|
||||
|
||||
0 [IF]
|
||||
h# 1f80 org
|
||||
\ the RAM Bootloader copies 2000-3f80 to 0-1f80, then branches to zero
|
||||
: bootloader
|
||||
h# 1f80 h# 0
|
||||
begin
|
||||
2dupxor
|
||||
while
|
||||
dup h# 2000 + @
|
||||
over !
|
||||
d# 2 +
|
||||
repeat
|
||||
|
||||
begin dsp h# ff and while drop repeat
|
||||
d# 0 >r
|
||||
;
|
||||
[ELSE]
|
||||
h# 3f80 org
|
||||
\ the Flash Bootloader copies 0x190000 to 0-3f80, then branches to zero
|
||||
: bootloader
|
||||
h# c flash_a_hi !
|
||||
h# 0 begin
|
||||
dup h# 8000 + flash_a !
|
||||
d# 0 flash_oe_n !
|
||||
flash_d @
|
||||
d# 1 flash_oe_n !
|
||||
over dup + !
|
||||
d# 1 +
|
||||
dup h# 1fc0 =
|
||||
until
|
||||
|
||||
begin dsp h# ff and while drop repeat
|
||||
d# 0 >r
|
||||
;
|
||||
[THEN]
|
||||
|
||||
4 org
|
||||
module[ everything"
|
||||
include nuc.fs
|
||||
|
||||
include version.fs
|
||||
|
||||
\ 33333333 / 115200 = 289, half cycle is 144
|
||||
|
||||
: pause144
|
||||
d# 0 d# 45
|
||||
begin
|
||||
1-
|
||||
2dup=
|
||||
until
|
||||
2drop
|
||||
;
|
||||
|
||||
: serout ( u -- )
|
||||
h# 300 or \ 1 stop bits
|
||||
2* \ 0 start bit
|
||||
\ Start bit
|
||||
begin
|
||||
dup RS232_TXD ! 2/
|
||||
pause144
|
||||
pause144
|
||||
dup 0=
|
||||
until
|
||||
drop
|
||||
pause144 pause144
|
||||
pause144 pause144
|
||||
;
|
||||
|
||||
: frac ( ud u -- d1 u1 ) \ d1+u1 is ud
|
||||
>r 2dup d# 1 r@ m*/ 2swap 2over r> d# 1 m*/ d- drop ;
|
||||
: .2 s>d <# # # #> type ;
|
||||
: build.
|
||||
decimal
|
||||
builddate drop
|
||||
[ -8 3600 * ] literal s>d d+
|
||||
d# 1 d# 60 m*/mod >r
|
||||
d# 1 d# 60 m*/mod >r
|
||||
d# 1 d# 24 m*/mod >r
|
||||
2drop
|
||||
r> .2 [char] : emit
|
||||
r> .2 [char] : emit
|
||||
r> .2 ;
|
||||
|
||||
: net-my-mac h# 1234 h# 5677 h# 7777 ;
|
||||
|
||||
include doc.fs
|
||||
include time.fs
|
||||
include eth-ax88796.fs
|
||||
include packet.fs
|
||||
include ip0.fs
|
||||
include defines_tcpip.fs
|
||||
include defines_tcpip2.fs
|
||||
include arp.fs
|
||||
include ip.fs
|
||||
include udp.fs
|
||||
include dhcp.fs
|
||||
|
||||
code in end-code
|
||||
: on ( a -- ) d# 1 swap ! ;
|
||||
code out end-code
|
||||
: off ( a -- ) d# 0 swap ! ;
|
||||
|
||||
: flash-reset
|
||||
flash_rst_n off
|
||||
flash_rst_n on
|
||||
;
|
||||
|
||||
: flash-cold
|
||||
flash_ddir on
|
||||
flash_ce_n off
|
||||
flash_oe_n on
|
||||
flash_we_n on
|
||||
flash_byte_n on
|
||||
flash_rdy on
|
||||
flash-reset
|
||||
;
|
||||
|
||||
: flash-w ( u a -- )
|
||||
flash_a !
|
||||
flash_d !
|
||||
flash_ddir off
|
||||
flash_we_n off
|
||||
flash_we_n on
|
||||
flash_ddir on
|
||||
;
|
||||
|
||||
: flash-r ( a -- u )
|
||||
flash_a !
|
||||
flash_oe_n off
|
||||
flash_d @
|
||||
flash_oe_n on
|
||||
;
|
||||
|
||||
: flash-unlock ( -- )
|
||||
h# aa h# 555 flash-w
|
||||
h# 55 h# 2aa flash-w
|
||||
;
|
||||
|
||||
: flash! ( u da. -- )
|
||||
flash-unlock
|
||||
h# a0 h# 555 flash-w
|
||||
flash_a 2+ ! ( u a )
|
||||
2dup ( u a u a)
|
||||
flash-w ( u a )
|
||||
begin
|
||||
2dup flash-r xor
|
||||
h# 80 and 0=
|
||||
until
|
||||
2drop
|
||||
flash-reset
|
||||
;
|
||||
|
||||
: flash@ ( da. -- u )
|
||||
flash_a 2+ ! ( u a )
|
||||
flash-r
|
||||
;
|
||||
|
||||
: flash-chiperase
|
||||
flash-unlock
|
||||
h# 80 h# 555 flash-w
|
||||
h# aa h# 555 flash-w
|
||||
h# 55 h# 2aa flash-w
|
||||
h# 10 h# 555 flash-w
|
||||
;
|
||||
|
||||
: flash-sectorerase ( da -- ) \ erase one sector
|
||||
flash-unlock
|
||||
h# 80 h# 555 flash-w
|
||||
h# aa h# 555 flash-w
|
||||
h# 55 h# 2aa flash-w
|
||||
flash_a 2+ ! h# 30 swap flash-w
|
||||
;
|
||||
|
||||
: flash-erased ( a -- f )
|
||||
flash@ h# 80 and 0<> ;
|
||||
|
||||
: flash-dump ( da u -- )
|
||||
0do
|
||||
2dup flash@ hex4 space
|
||||
d1+
|
||||
loop cr
|
||||
2drop
|
||||
;
|
||||
|
||||
: flashc@
|
||||
over d# 15 lshift flash_d !
|
||||
d2/ flash@
|
||||
;
|
||||
|
||||
: flash-bytes
|
||||
s" BYTES: " type
|
||||
flash_byte_n off
|
||||
h# 0.
|
||||
d# 1024 0do
|
||||
i d# 15 and 0= if
|
||||
cr
|
||||
2dup hex8 space space
|
||||
then
|
||||
2dup flashc@ hex2 space
|
||||
d1+
|
||||
loop cr
|
||||
2drop
|
||||
flash_byte_n on
|
||||
;
|
||||
|
||||
0 [IF]
|
||||
: flash-demo
|
||||
flash-unlock
|
||||
h# 90 h# 555 flash-w
|
||||
h# 00 flash-r hex4 cr
|
||||
flash-reset
|
||||
|
||||
false if
|
||||
flash-unlock
|
||||
h# a0 h# 555 flash-w
|
||||
h# 0947 h# 5 flash-w
|
||||
sleep1
|
||||
flash-reset
|
||||
then
|
||||
|
||||
\ h# dead d# 11. flash!
|
||||
|
||||
h# 100 0do
|
||||
i flash-r hex4 space
|
||||
loop cr
|
||||
cr cr
|
||||
d# 0. h# 80 flash-dump
|
||||
cr cr
|
||||
|
||||
flash-bytes
|
||||
|
||||
exit
|
||||
flash-unlock
|
||||
h# 80 h# 555 flash-w
|
||||
h# aa h# 555 flash-w
|
||||
h# 55 h# 2aa flash-w
|
||||
h# 10 h# 555 flash-w
|
||||
s" waiting for erase" type cr
|
||||
begin
|
||||
h# 0 flash-r dup hex4 cr
|
||||
h# 80 and
|
||||
until
|
||||
|
||||
h# 100 0do
|
||||
i flash-r hex4 space
|
||||
loop cr
|
||||
;
|
||||
[THEN]
|
||||
|
||||
include sprite.fs
|
||||
|
||||
variable cursory \ ptr to start of line in video memory
|
||||
variable cursorx \ offset to char
|
||||
|
||||
64 constant width
|
||||
50 constant wrapcolumn
|
||||
|
||||
: vga-at-xy ( u1 u2 )
|
||||
cursory !
|
||||
cursorx !
|
||||
;
|
||||
|
||||
: home d# 0 vga_scroll ! d# 0 d# 0 vga-at-xy ;
|
||||
|
||||
: vga-line ( -- a ) \ address of current line
|
||||
cursory @ vga_scroll @ + d# 31 and d# 6 lshift
|
||||
h# 8000 or
|
||||
;
|
||||
|
||||
: vga-erase ( a u -- )
|
||||
bounds begin
|
||||
2dupxor
|
||||
while
|
||||
h# 00 over ! 1+
|
||||
repeat 2drop
|
||||
;
|
||||
|
||||
: vga-page
|
||||
home vga-line d# 2048 vga-erase
|
||||
hide
|
||||
;
|
||||
|
||||
: down1
|
||||
cursory @ d# 31 <> if
|
||||
d# 1 cursory +!
|
||||
else
|
||||
false if
|
||||
d# 1 vga_scroll +!
|
||||
vga-line width vga-erase
|
||||
else
|
||||
home
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
: vga-emit ( c -- )
|
||||
dup d# 13 = if
|
||||
drop d# 0 cursorx !
|
||||
else
|
||||
dup d# 10 = if
|
||||
drop down1
|
||||
else
|
||||
d# -32 +
|
||||
vga-line cursorx @ + !
|
||||
d# 1 cursorx +!
|
||||
cursorx @ wrapcolumn = if
|
||||
d# 0 cursorx !
|
||||
down1
|
||||
then
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
: flash>ram ( d. a -- ) \ copy 2K from flash d to a
|
||||
>r d2/ r>
|
||||
d# 1024 0do
|
||||
>r
|
||||
2dup flash@
|
||||
r> ( d. u a )
|
||||
over swab over !
|
||||
1+
|
||||
tuck !
|
||||
1+
|
||||
>r d1+ r>
|
||||
loop
|
||||
drop 2drop
|
||||
;
|
||||
|
||||
: vga-cold
|
||||
h# f800 h# f000 do
|
||||
d# 0 i !
|
||||
loop
|
||||
|
||||
vga-page
|
||||
|
||||
\ pic: Copy 2048 bytes from 180000 to 8000
|
||||
\ chr: Copy 2048 bytes from 180800 to f000
|
||||
h# 180000. h# 8000 flash>ram
|
||||
h# 180800. h# f000 flash>ram
|
||||
|
||||
\ ['] vga-emit 'emit !
|
||||
;
|
||||
|
||||
create glyph 8 allot
|
||||
: wide1 ( c -- )
|
||||
swab
|
||||
d# 8 0do
|
||||
dup 0<
|
||||
if d# 127 else sp then
|
||||
\ if [char] * else [char] . then
|
||||
vga-emit
|
||||
2*
|
||||
loop drop
|
||||
;
|
||||
|
||||
: vga-bigemit ( c -- )
|
||||
dup d# 13 = if
|
||||
drop d# 0 cursorx !
|
||||
else
|
||||
dup d# 10 = if
|
||||
drop d# 8 0do down1 loop
|
||||
else
|
||||
sp - d# 8 * s>d
|
||||
h# 00180800. d+ d2/
|
||||
d# 4 0do
|
||||
2dup flash@ swab
|
||||
i cells glyph + !
|
||||
d1+
|
||||
loop 2drop
|
||||
|
||||
d# 7 0do
|
||||
i glyph + c@ wide1
|
||||
d# -8 cursorx +! down1
|
||||
loop
|
||||
d# 7 glyph + c@ wide1
|
||||
|
||||
d# -7 cursory +!
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
( Demo utilities JCB 10:56 12/05/10)
|
||||
|
||||
: statusline ( a u -- ) \ display string on the status line
|
||||
d# 0 d# 31 2dup vga-at-xy
|
||||
d# 50 spaces
|
||||
vga-at-xy type
|
||||
;
|
||||
|
||||
( Game stuff JCB 15:20 11/15/10)
|
||||
|
||||
variable seed
|
||||
: random ( -- u )
|
||||
seed @ d# 23947 * d# 57711 xor dup seed ! ;
|
||||
|
||||
|
||||
\ Each line is 20.8 us, so 1000 instructions
|
||||
|
||||
include sincos.fs
|
||||
|
||||
( Stars JCB 15:23 11/15/10)
|
||||
|
||||
2variable vision
|
||||
variable frame
|
||||
128 constant nstars
|
||||
create stars 1024 allot
|
||||
|
||||
: star 2* cells stars + ;
|
||||
: 15.* m* d2* nip ;
|
||||
|
||||
\ >>> math.cos(math.pi / 180) * 32767
|
||||
\ 32762.009427189474
|
||||
\ >>> math.sin(math.pi / 180) * 32767
|
||||
\ 571.8630017304688
|
||||
|
||||
[ pi 128e0 f/ fcos 32767e0 f* f>d drop ] constant COSa
|
||||
[ pi 128e0 f/ fsin 32767e0 f* f>d drop ] constant SINa
|
||||
|
||||
: rotate ( i -- ) \ rotate star i
|
||||
star dup 2@ ( x y )
|
||||
over SINa 15.* over COSa 15.* + >r
|
||||
swap COSa 15.* swap SINa 15.* - r>
|
||||
rot 2!
|
||||
;
|
||||
|
||||
: rotateall
|
||||
d# 256 0do i rotate loop ;
|
||||
|
||||
: scatterR
|
||||
nstars 0do
|
||||
random d# 0 i star 2!
|
||||
rotateall
|
||||
rotateall
|
||||
rotateall
|
||||
rotateall
|
||||
loop
|
||||
;
|
||||
|
||||
: scatterSpiral
|
||||
nstars 0do
|
||||
i d# 3 and 1+ d# 8000 *
|
||||
d# 0 i star 2!
|
||||
rotateall
|
||||
rotateall
|
||||
rotateall
|
||||
rotateall
|
||||
loop
|
||||
;
|
||||
|
||||
: scatter
|
||||
nstars 0do
|
||||
\ d# 0 random
|
||||
d# 0 i sin
|
||||
i star 2!
|
||||
i random d# 255 and 0do
|
||||
dup rotate
|
||||
loop drop
|
||||
loop
|
||||
;
|
||||
|
||||
: /128 dup 0< h# fe00 and swap d# 7 rshift or ;
|
||||
: tx /128 [ 400 ] literal + ;
|
||||
: ty /128 [ 256 ] literal + ;
|
||||
|
||||
: plot ( i s ) \ plot star i in sprite s
|
||||
>r
|
||||
dup star @ tx swap d# 2 lshift
|
||||
r> sprite!
|
||||
;
|
||||
|
||||
( Display list JCB 16:10 11/15/10)
|
||||
|
||||
create dl 1026 allot
|
||||
|
||||
: erasedl
|
||||
dl d# 1024 bounds begin
|
||||
d# -1 over !
|
||||
cell+ 2dup=
|
||||
until 2drop
|
||||
;
|
||||
|
||||
: makedl
|
||||
erasedl
|
||||
|
||||
nstars 0do
|
||||
i d# 2 lshift
|
||||
cells dl +
|
||||
\ cell occupied, use one below
|
||||
\ dup @ 0< invert if cell+ then
|
||||
i swap !
|
||||
loop
|
||||
;
|
||||
|
||||
variable lastsp
|
||||
: stars-chasebeam
|
||||
hide
|
||||
d# 0 lastsp !
|
||||
d# 512 0do
|
||||
begin vga-line@ i = until
|
||||
i cells dl + @ dup 0< if
|
||||
drop
|
||||
else
|
||||
lastsp @ 1+ d# 7 and dup lastsp ! plot
|
||||
then
|
||||
i nstars < if i rotate then
|
||||
loop
|
||||
;
|
||||
|
||||
|
||||
|
||||
: loadcolors
|
||||
d# 8 0do
|
||||
dup @
|
||||
i cells vga_spritec + !
|
||||
cell+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
create cpastels
|
||||
h# 423 ,
|
||||
h# 243 ,
|
||||
h# 234 ,
|
||||
h# 444 ,
|
||||
h# 324 ,
|
||||
h# 432 ,
|
||||
h# 342 ,
|
||||
h# 244 ,
|
||||
: pastels cpastels loadcolors ;
|
||||
|
||||
create crainbow
|
||||
h# 400 ,
|
||||
h# 440 ,
|
||||
h# 040 ,
|
||||
h# 044 ,
|
||||
h# 004 ,
|
||||
h# 404 ,
|
||||
h# 444 ,
|
||||
h# 444 ,
|
||||
: rainbow crainbow loadcolors ;
|
||||
|
||||
variable prev_sw3_n
|
||||
|
||||
: next? ( -- f ) \ has user requested next screen
|
||||
sw3_n @ prev_sw3_n fall?
|
||||
;
|
||||
|
||||
: loadsprites ( da -- )
|
||||
2/
|
||||
d# 16384 0do
|
||||
2dup i s>d d+ flash@
|
||||
i vga_spritea ! vga_spriteport !
|
||||
loop
|
||||
2drop
|
||||
;
|
||||
|
||||
: stars-main
|
||||
vga-page
|
||||
d# 16384 0do
|
||||
h# 204000. 2/ i s>d d+ flash@
|
||||
i vga_spritea ! vga_spriteport !
|
||||
loop
|
||||
|
||||
vga_addsprites on
|
||||
rainbow
|
||||
|
||||
time@ xor seed !
|
||||
seed off
|
||||
scatter
|
||||
|
||||
d# 7000000. vision setalarm
|
||||
d# 0 frame !
|
||||
begin
|
||||
makedl
|
||||
stars-chasebeam
|
||||
\ d# 256 0do i i plot loop
|
||||
\ rotateall
|
||||
frame @ 1+ frame !
|
||||
next?
|
||||
until
|
||||
frame @ . s" frames" type cr
|
||||
;
|
||||
|
||||
: buttons ( -- u ) \ pb4 pb3 pb2
|
||||
pb_a_dir on
|
||||
pb_a @ d# 7 xor
|
||||
pb_a_dir off
|
||||
;
|
||||
|
||||
include loader.fs
|
||||
include dns.fs
|
||||
|
||||
: preip-handler
|
||||
begin
|
||||
mac-fullness
|
||||
while
|
||||
OFFSET_ETH_TYPE packet@ h# 800 = if
|
||||
dhcp-wait-offer
|
||||
then
|
||||
mac-consume
|
||||
repeat
|
||||
;
|
||||
|
||||
: haveip-handler
|
||||
\ time@ begin ether_irq @ until time@ 2swap d- d. cr
|
||||
\ begin ether_irq @ until
|
||||
begin
|
||||
mac-fullness
|
||||
while
|
||||
arp-handler
|
||||
OFFSET_ETH_TYPE packet@ h# 800 =
|
||||
if
|
||||
d# 2 OFFSET_IP_DSTIP mac-inoffset mac@n net-my-ip d=
|
||||
if
|
||||
icmp-handler
|
||||
then
|
||||
loader-handler
|
||||
then
|
||||
depth if .s cr then
|
||||
mac-consume
|
||||
repeat
|
||||
;
|
||||
|
||||
include invaders.fs
|
||||
|
||||
: uptime
|
||||
time@
|
||||
d# 1 d# 1000 m*/
|
||||
d# 1 d# 1000 m*/
|
||||
;
|
||||
|
||||
( IP address formatting JCB 14:50 10/26/10)
|
||||
|
||||
: #ip1 h# ff and s>d #s 2drop ;
|
||||
: #. [char] . hold ;
|
||||
: #ip2 dup #ip1 #. d# 8 rshift #ip1 ;
|
||||
: #ip ( ip -- c-addr u) dup #ip2 #. over #ip2 ;
|
||||
|
||||
variable prev_sw2_n
|
||||
: sw2? sw2_n @ prev_sw2_n fall? ;
|
||||
|
||||
include ps2kb.fs
|
||||
|
||||
: istab?
|
||||
key? dup if key TAB = and then
|
||||
;
|
||||
|
||||
: welcome-main
|
||||
vga-cold
|
||||
home
|
||||
s" F1 to set up network, TAB for next demo" statusline
|
||||
|
||||
rainbow
|
||||
h# 200000. loadsprites
|
||||
'emit @ >r
|
||||
d# 6 d# 26 vga-at-xy s" Softcore Forth CPU" type
|
||||
|
||||
d# 32 d# 6 vga-at-xy s" version " type version type
|
||||
d# 32 d# 8 vga-at-xy s" built " type build.
|
||||
|
||||
kb-cold
|
||||
home
|
||||
begin
|
||||
kbfifo-proc
|
||||
d# 32 d# 10 vga-at-xy net-my-ip <# #ip #> type space space
|
||||
d# 32 d# 12 vga-at-xy s" uptime " type uptime d.
|
||||
haveip-handler
|
||||
|
||||
d# 8 0do
|
||||
frame @ i d# 32 * + invert >r
|
||||
d# 100 r@ sin* d# 600 +
|
||||
d# 100 r> cos* d# 334 +
|
||||
i sprite!
|
||||
loop
|
||||
|
||||
waitblank
|
||||
d# 1 frame +!
|
||||
next?
|
||||
istab? or
|
||||
until
|
||||
r> 'emit !
|
||||
;
|
||||
|
||||
include clock.fs
|
||||
|
||||
: frob
|
||||
flash_ce_n on
|
||||
flash_ddir off
|
||||
d# 32 0do
|
||||
d# 1 i d# 7 and lshift
|
||||
flash_d !
|
||||
d# 30000. sleepus
|
||||
loop
|
||||
flash_ddir on
|
||||
;
|
||||
|
||||
: main
|
||||
decimal
|
||||
['] serout 'emit !
|
||||
\ sleep1
|
||||
|
||||
frob
|
||||
|
||||
d# 60 0do cr loop
|
||||
s" Welcome! Built " type build. cr
|
||||
snap
|
||||
|
||||
flash-cold
|
||||
\ flash-demo
|
||||
\ flash-bytes
|
||||
vga-cold
|
||||
['] vga-emit 'emit !
|
||||
s" Waiting for Ethernet NIC" statusline
|
||||
mac-cold
|
||||
nicwork
|
||||
h# decafbad. dhcp-xid!
|
||||
d# 3000000. dhcp-alarm setalarm
|
||||
false if
|
||||
ip-addr dz
|
||||
begin
|
||||
net-my-ip d0=
|
||||
while
|
||||
dhcp-alarm isalarm if
|
||||
dhcp-discover
|
||||
s" DISCOVER" type cr
|
||||
d# 3000000. dhcp-alarm setalarm
|
||||
then
|
||||
preip-handler
|
||||
repeat
|
||||
else
|
||||
ip# 192.168.0.99 ip-addr 2!
|
||||
ip# 255.255.255.0 ip-subnetmask 2!
|
||||
ip# 192.168.0.1 ip-router 2!
|
||||
\ ip# 192.168.2.201 ip-addr 2!
|
||||
\ ip# 255.255.255.0 ip-subnetmask 2!
|
||||
\ ip# 192.168.2.1 ip-router 2!
|
||||
then
|
||||
dhcp-status
|
||||
arp-reset
|
||||
|
||||
begin
|
||||
welcome-main sleep.1
|
||||
clock-main sleep.1
|
||||
stars-main sleep.1
|
||||
invaders-main sleep.1
|
||||
s" looping" type cr
|
||||
again
|
||||
|
||||
begin
|
||||
haveip-handler
|
||||
again
|
||||
;
|
||||
|
||||
|
||||
]module
|
||||
|
||||
0 org
|
||||
|
||||
code 0jump
|
||||
\ h# 3e00 ubranch
|
||||
main ubranch
|
||||
main ubranch
|
||||
end-code
|
||||
|
||||
meta
|
||||
|
||||
hex
|
||||
|
||||
: create-output-file w/o create-file throw to outfile ;
|
||||
|
||||
\ .mem is a memory dump formatted for use with the Xilinx
|
||||
\ data2mem tool.
|
||||
s" j1.mem" create-output-file
|
||||
:noname
|
||||
s" @ 20000" type cr
|
||||
4000 0 do i t@ s>d <# # # # # #> type cr 2 +loop
|
||||
; execute
|
||||
|
||||
\ .bin is a big-endian binary memory dump
|
||||
s" j1.bin" create-output-file
|
||||
:noname 4000 0 do i t@ dup 8 rshift emit emit 2 +loop ; execute
|
||||
|
||||
\ .lst file is a human-readable disassembly
|
||||
s" j1.lst" create-output-file
|
||||
d# 0
|
||||
h# 2000 disassemble-block
|
||||
14
j1/firmware/mkblob.py
Normal file
14
j1/firmware/mkblob.py
Normal file
@ -0,0 +1,14 @@
|
||||
import Image
|
||||
import math
|
||||
|
||||
im = Image.new("L", (32,32))
|
||||
radius = 16
|
||||
for i in range(32):
|
||||
for j in range(32):
|
||||
x = abs(i - 16)
|
||||
y = abs(j - 16)
|
||||
d = math.sqrt(x * x + y * y)
|
||||
if d < radius:
|
||||
t = 1.0 - (d / radius)
|
||||
im.putpixel((i, j), int(255 * (t * t)))
|
||||
im.save("blob.png")
|
||||
36
j1/firmware/ntp.fs
Normal file
36
j1/firmware/ntp.fs
Normal file
@ -0,0 +1,36 @@
|
||||
( NTP JCB 09:54 11/17/10)
|
||||
|
||||
: ntp-server
|
||||
\ h# 02830a00.
|
||||
\ ip# 91.189.94.4 \ time.ubuntu
|
||||
ip# 17.151.16.20 \ time.apple.com
|
||||
;
|
||||
|
||||
: ntp-request
|
||||
d# 123 d# 9999
|
||||
ntp-server
|
||||
net-my-ip
|
||||
2over arp-lookup
|
||||
( dst-port src-port dst-ip src-ip *ethaddr )
|
||||
udp-header
|
||||
h# 2304 mac-pkt-, h# 04ec mac-pkt-,
|
||||
d# 6 mac-pkt-,0
|
||||
|
||||
d# 4 mac-pkt-,0 \ originate
|
||||
d# 4 mac-pkt-,0 \ reference
|
||||
d# 4 mac-pkt-,0 \ receive
|
||||
\ d# 4 mac-pkt-,0 \ transmit
|
||||
time@ mac-pkt-d, d# 2 mac-pkt-,0
|
||||
udp-wrapup mac-send
|
||||
;
|
||||
|
||||
: ntp-handler
|
||||
IP_PROTO_UDP ip-isproto
|
||||
ETH.IP.UDP.SOURCEPORT packet@ d# 123 = and
|
||||
ETH.IP.UDP.DESTPORT packet@ d# 9999 = and
|
||||
if
|
||||
ETH.IP.UDP.NTP.TRANSMIT packetd@ setdate
|
||||
time@ ETH.IP.UDP.NTP.ORIGINATE packetd@ d- setdelay
|
||||
then
|
||||
;
|
||||
|
||||
546
j1/firmware/nuc.fs
Normal file
546
j1/firmware/nuc.fs
Normal file
@ -0,0 +1,546 @@
|
||||
( Nucleus: ANS Forth core and ext words JCB 13:11 08/24/10)
|
||||
|
||||
module[ nuc"
|
||||
|
||||
32 constant sp
|
||||
0 constant false ( 6.2.1485 )
|
||||
: depth dsp h# ff and ;
|
||||
: true ( 6.2.2298 ) d# -1 ;
|
||||
: 1+ d# 1 + ;
|
||||
: rot >r swap r> swap ;
|
||||
: -rot swap >r swap r> ;
|
||||
: 0= d# 0 = ;
|
||||
: tuck swap over ;
|
||||
: 2drop drop drop ;
|
||||
: ?dup dup if dup then ;
|
||||
|
||||
: split ( a m -- a&m a&~m )
|
||||
over \ a m a
|
||||
and \ a a&m
|
||||
tuck \ a&m a a&m
|
||||
xor \ a&m a&~m
|
||||
;
|
||||
|
||||
: merge ( a b m -- m?b:a )
|
||||
>r \ a b
|
||||
over xor \ a a^b
|
||||
r> and \ a (a^b)&m
|
||||
xor \ ((a^b)&m)^a
|
||||
;
|
||||
|
||||
: c@ dup @ swap d# 1 and if d# 8 rshift else d# 255 and then ;
|
||||
: c! ( u c-addr )
|
||||
swap h# ff and dup d# 8 lshift or swap
|
||||
tuck dup @ swap ( c-addr u v c-addr )
|
||||
d# 1 and d# 0 = h# ff xor
|
||||
merge swap !
|
||||
;
|
||||
: c!be d# 1 xor c! ;
|
||||
|
||||
: looptest ( -- FIN )
|
||||
r> ( xt )
|
||||
r> ( xt i )
|
||||
1+
|
||||
r@ over = ( xt i FIN )
|
||||
dup if
|
||||
nip r> drop
|
||||
else
|
||||
swap >r
|
||||
then ( xt FIN )
|
||||
swap
|
||||
>r
|
||||
;
|
||||
|
||||
\ Stack
|
||||
: 2dup over over ;
|
||||
: +! tuck @ + swap ! ;
|
||||
|
||||
\ Comparisons
|
||||
: <> = invert ;
|
||||
: 0<> 0= invert ;
|
||||
: 0< d# 0 < ;
|
||||
: 0>= 0< invert ;
|
||||
: 0> d# 0 ;fallthru
|
||||
: > swap < ;
|
||||
: >= < invert ;
|
||||
: <= > invert ;
|
||||
: u> swap u< ;
|
||||
|
||||
\ Arithmetic
|
||||
: negate invert 1+ ;
|
||||
: - negate + ;
|
||||
: abs dup 0< if negate then ;
|
||||
: min 2dup < ;fallthru
|
||||
: ?: ( xt xf f -- xt | xf) if drop else nip then ;
|
||||
: max 2dup > ?: ;
|
||||
code cells end-code
|
||||
code addrcells end-code
|
||||
: 2* d# 1 lshift ;
|
||||
code cell+ end-code
|
||||
code addrcell+ end-code
|
||||
: 2+ d# 2 + ;
|
||||
: 2- 1- 1- ;
|
||||
: 2/ d# 1 rshift ;
|
||||
: c+! tuck c@ + swap c! ;
|
||||
|
||||
: count dup 1+ swap c@ ;
|
||||
: /string dup >r - swap r> + swap ;
|
||||
: aligned 1+ h# fffe and ;
|
||||
|
||||
: sliteral
|
||||
r>
|
||||
count
|
||||
2dup
|
||||
+
|
||||
aligned
|
||||
;fallthru
|
||||
: execute >r ;
|
||||
|
||||
: 15down down1 ;fallthru
|
||||
: 14down down1 ;fallthru
|
||||
: 13down down1 ;fallthru
|
||||
: 12down down1 ;fallthru
|
||||
: 11down down1 ;fallthru
|
||||
: 10down down1 ;fallthru
|
||||
: 9down down1 ;fallthru
|
||||
: 8down down1 ;fallthru
|
||||
: 7down down1 ;fallthru
|
||||
: 6down down1 ;fallthru
|
||||
: 5down down1 ;fallthru
|
||||
: 4down down1 ;fallthru
|
||||
: 3down down1 ;fallthru
|
||||
: 2down down1 ;fallthru
|
||||
: 1down down1 ;fallthru
|
||||
: 0down copy ;
|
||||
|
||||
: 15up up1 ;fallthru
|
||||
: 14up up1 ;fallthru
|
||||
: 13up up1 ;fallthru
|
||||
: 12up up1 ;fallthru
|
||||
: 11up up1 ;fallthru
|
||||
: 10up up1 ;fallthru
|
||||
: 9up up1 ;fallthru
|
||||
: 8up up1 ;fallthru
|
||||
: 7up up1 ;fallthru
|
||||
: 6up up1 ;fallthru
|
||||
: 5up up1 ;fallthru
|
||||
: 4up up1 ;fallthru
|
||||
: 3up up1 ;fallthru
|
||||
: 2up up1 ;fallthru
|
||||
: 1up up1 ;fallthru
|
||||
: 0up ;
|
||||
|
||||
code pickbody
|
||||
copy return
|
||||
1down scall 1up ubranch
|
||||
2down scall 2up ubranch
|
||||
3down scall 3up ubranch
|
||||
4down scall 4up ubranch
|
||||
5down scall 5up ubranch
|
||||
6down scall 6up ubranch
|
||||
7down scall 7up ubranch
|
||||
8down scall 8up ubranch
|
||||
9down scall 9up ubranch
|
||||
10down scall 10up ubranch
|
||||
11down scall 11up ubranch
|
||||
12down scall 12up ubranch
|
||||
13down scall 13up ubranch
|
||||
14down scall 14up ubranch
|
||||
15down scall 15up ubranch
|
||||
end-code
|
||||
|
||||
: pick
|
||||
dup 2* 2* ['] pickbody + execute ;
|
||||
|
||||
: swapdown
|
||||
]asm
|
||||
N T->N alu
|
||||
T d-1 alu
|
||||
asm[
|
||||
;
|
||||
: swapdowns
|
||||
swapdown swapdown swapdown swapdown
|
||||
swapdown swapdown swapdown swapdown
|
||||
swapdown swapdown swapdown swapdown
|
||||
swapdown swapdown swapdown swapdown ;fallthru
|
||||
: swapdown0 ;
|
||||
: roll
|
||||
2*
|
||||
['] 0up over - >r
|
||||
['] swapdown0 swap - execute
|
||||
;
|
||||
|
||||
\ ========================================================================
|
||||
\ Double
|
||||
\ ========================================================================
|
||||
|
||||
: d= ( a b c d -- f )
|
||||
>r \ a b c
|
||||
rot xor \ b a^c
|
||||
swap r> xor \ a^c b^d
|
||||
or 0=
|
||||
;
|
||||
|
||||
: 2@ ( ptr -- lo hi )
|
||||
dup @ swap 2+ @
|
||||
;
|
||||
|
||||
: 2! ( lo hi ptr -- )
|
||||
rot over \ hi ptr lo ptr
|
||||
! 2+ !
|
||||
;
|
||||
|
||||
: 2over >r >r 2dup r> r> ;fallthru
|
||||
: 2swap rot >r rot r> ;
|
||||
: 2nip rot drop rot drop ;
|
||||
: 2rot ( d1 d2 d3 -- d2 d3 d1 ) 2>r 2swap 2r> 2swap ;
|
||||
: 2pick
|
||||
2* 1+ dup 1+ \ lo hi ... 2k+1 2k+2
|
||||
pick \ lo hi ... 2k+1 lo
|
||||
swap \ lo hi ... lo 2k+1
|
||||
pick \ lo hi ... lo hi
|
||||
;
|
||||
|
||||
|
||||
: d+ ( augend . addend . -- sum . )
|
||||
rot + >r ( augend addend)
|
||||
over + ( augend sum)
|
||||
dup rot ( sum sum augend)
|
||||
u< if ( sum)
|
||||
r> 1+
|
||||
else
|
||||
r>
|
||||
then ( sum . )
|
||||
;
|
||||
|
||||
: +h ( u1 u2 -- u1+u2/2**16 )
|
||||
over + ( a a+b )
|
||||
u> d# 1 and
|
||||
;
|
||||
|
||||
: +1c \ one's complement add, as in TCP checksum
|
||||
2dup +h + +
|
||||
;
|
||||
|
||||
: s>d dup 0< ;
|
||||
: d1+ d# 1. d+ ;
|
||||
: dnegate
|
||||
invert swap invert swap
|
||||
d1+
|
||||
;
|
||||
: DABS ( d -- ud ) ( 8.6.1.1160 ) DUP 0< IF DNEGATE THEN ;
|
||||
|
||||
: d- dnegate d+ ;
|
||||
|
||||
\ Write zero to double
|
||||
: dz d# 0 dup rot 2! ;
|
||||
|
||||
: dxor \ ( a b c d -- e f )
|
||||
rot xor \ a c b^d
|
||||
-rot xor \ b^d a^c
|
||||
swap
|
||||
;
|
||||
|
||||
: dand rot and -rot and swap ;
|
||||
: dor rot or -rot or swap ;
|
||||
|
||||
: dinvert invert swap invert swap ;
|
||||
: d< \ ( al ah bl bh -- flag )
|
||||
rot \ al bl bh ah
|
||||
2dup =
|
||||
if
|
||||
2drop u<
|
||||
else
|
||||
2nip >
|
||||
then
|
||||
;
|
||||
|
||||
: d> 2swap d< ;
|
||||
: d0<= d# 0. ;fallthru
|
||||
: d<= d> invert ;
|
||||
: d>= d< invert ;
|
||||
: d0= or 0= ;
|
||||
: d0< d# 0. d< ;
|
||||
: d0<> d0= invert ;
|
||||
: d<> d= invert ;
|
||||
: d2* 2dup d+ ;
|
||||
: d2/ dup d# 15 lshift >r 2/ swap 2/ r> or swap ;
|
||||
: dmax 2over 2over d< if 2swap then 2drop ;
|
||||
|
||||
: d1- d# -1. d+ ;
|
||||
|
||||
: d+! ( v. addr -- )
|
||||
dup >r
|
||||
2@
|
||||
d+
|
||||
r>
|
||||
2!
|
||||
;
|
||||
|
||||
: move ( addr1 addr2 u -- )
|
||||
d# 0 do
|
||||
over @ over !
|
||||
2+ swap 2+ swap
|
||||
loop
|
||||
2drop
|
||||
;
|
||||
|
||||
: cmove ( c-addr1 c-addr2 u -- )
|
||||
d# 0 do
|
||||
over c@ over c!
|
||||
1+ swap 1+ swap
|
||||
loop
|
||||
2drop
|
||||
;
|
||||
|
||||
: bounds ( a n -- a+n a ) OVER + SWAP ;
|
||||
: fill ( c-addr u char -- ) ( 6.1.1540 )
|
||||
>R bounds
|
||||
BEGIN 2dupxor
|
||||
WHILE R@ OVER C! 1+
|
||||
REPEAT R> DROP 2DROP ;
|
||||
|
||||
\ Math
|
||||
|
||||
0 [IF]
|
||||
create scratch d# 2 allot
|
||||
: um* ( u1 u2 -- ud )
|
||||
scratch !
|
||||
d# 0.
|
||||
d# 16 0do
|
||||
2dup d+
|
||||
rot dup 0< if
|
||||
2* -rot
|
||||
scratch @ d# 0 d+
|
||||
else
|
||||
2* -rot
|
||||
then
|
||||
loop
|
||||
rot drop
|
||||
;
|
||||
[ELSE]
|
||||
: um* mult_a ! mult_b ! mult_p 2@ ;
|
||||
[THEN]
|
||||
|
||||
: * um* drop ;
|
||||
: abssgn ( a b -- |a| |b| negf )
|
||||
2dup xor 0< >r abs swap abs swap r> ;
|
||||
|
||||
: m* abssgn >r um* r> if dnegate then ;
|
||||
|
||||
: divstep
|
||||
( divisor dq hi )
|
||||
2*
|
||||
over 0< if 1+ then
|
||||
swap 2* swap
|
||||
rot ( dq hi divisor )
|
||||
2dup >= if
|
||||
tuck ( dq divisor hi divisor )
|
||||
-
|
||||
swap ( dq hi divisor )
|
||||
rot 1+ ( hi divisor dq )
|
||||
rot ( divisor dq hi )
|
||||
else
|
||||
-rot
|
||||
then
|
||||
;
|
||||
|
||||
: um/mod ( ud u1 -- u2 u3 ) ( 6.1.2370 )
|
||||
-rot
|
||||
divstep divstep divstep divstep
|
||||
divstep divstep divstep divstep
|
||||
divstep divstep divstep divstep
|
||||
divstep divstep divstep divstep
|
||||
rot drop swap
|
||||
;
|
||||
|
||||
: /mod >R S>D R> ;fallthru
|
||||
: SM/REM ( d n -- r q ) ( 6.1.2214 ) ( symmetric )
|
||||
OVER >R >R DABS R@ ABS UM/MOD
|
||||
R> R@ XOR 0< IF NEGATE THEN R> 0< IF >R NEGATE R> THEN ;
|
||||
: / /mod nip ;
|
||||
: mod /mod drop ;
|
||||
: */mod >R M* R> SM/REM ;
|
||||
: */ */mod nip ;
|
||||
|
||||
: t2* over >r >r d2*
|
||||
r> 2* r> 0< d# 1 and + ;
|
||||
|
||||
variable divisor
|
||||
: m*/mod
|
||||
divisor !
|
||||
tuck um* 2swap um* ( hi. lo. )
|
||||
( m0 h l m1 )
|
||||
swap >r d# 0 d+ r> ( m h l )
|
||||
-rot ( l m h )
|
||||
d# 32 0do
|
||||
t2*
|
||||
dup divisor @ >= if
|
||||
divisor @ -
|
||||
rot 1+ -rot
|
||||
then
|
||||
loop
|
||||
;
|
||||
: m*/ m*/mod drop ;
|
||||
|
||||
|
||||
\ Numeric output - from eforth
|
||||
|
||||
variable base
|
||||
variable hld
|
||||
create pad 84 allot create pad|
|
||||
|
||||
: <# ( -- ) ( 6.1.0490 )( h# 96 ) pad| HLD ! ;
|
||||
: DIGIT ( u -- c ) d# 9 OVER < d# 7 AND + [CHAR] 0 + ;
|
||||
: HOLD ( c -- ) ( 6.1.1670 ) HLD @ 1- DUP HLD ! C! ;
|
||||
|
||||
: # ( d -- d ) ( 6.1.0030 )
|
||||
d# 0 BASE @ UM/MOD >R BASE @ UM/MOD SWAP DIGIT HOLD R> ;
|
||||
|
||||
: #S ( d -- d ) ( 6.1.0050 ) BEGIN # 2DUP OR 0= UNTIL ;
|
||||
: #> ( d -- a u ) ( 6.1.0040 ) 2DROP HLD @ pad| OVER - ;
|
||||
|
||||
: SIGN ( n -- ) ( 6.1.2210 ) 0< IF [CHAR] - HOLD THEN ;
|
||||
|
||||
\ hex(int((1<<24) * (115200 / 2400.) / (WB_CLOCK_FREQ / 2400.)))
|
||||
\ d# 42000000 constant WB_CLOCK_FREQ
|
||||
|
||||
[ 48000000 17 12 */ ] constant WB_CLOCK_FREQ
|
||||
|
||||
0 [IF]
|
||||
: uartbase
|
||||
[ $100000000. 115200 WB_CLOCK_FREQ m*/ drop $ffffff00 and dup swap 16 rshift ] 2literal
|
||||
;
|
||||
: emit-uart
|
||||
begin uart_0 @ 0= until
|
||||
s>d
|
||||
uartbase dor
|
||||
uart_1 ! uart_0 !
|
||||
;
|
||||
[ELSE]
|
||||
: emit-uart drop ;
|
||||
[THEN]
|
||||
|
||||
create 'emit
|
||||
meta emit-uart t, target
|
||||
|
||||
: emit 'emit @ execute ;
|
||||
: cr d# 13 emit d# 10 emit ;
|
||||
d# 32 constant bl
|
||||
: space bl emit ;
|
||||
: spaces begin dup 0> while space 1- repeat drop ;
|
||||
|
||||
: hex1 d# 15 and dup d# 10 < if d# 48 else d# 55 then + emit ;
|
||||
: hex2
|
||||
dup
|
||||
d# 4 rshift
|
||||
hex1 hex1
|
||||
;
|
||||
: hex4
|
||||
dup
|
||||
d# 8 rshift
|
||||
hex2 hex2 ;
|
||||
|
||||
: hex8 hex4 hex4 ;
|
||||
|
||||
: type
|
||||
d# 0 do
|
||||
dup c@ emit
|
||||
1+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
: dump
|
||||
( addr u )
|
||||
0do
|
||||
dup d# 15 and 0= if dup cr hex4 [char] : emit space space then
|
||||
dup c@ hex2 space 1+
|
||||
loop
|
||||
cr drop
|
||||
;
|
||||
|
||||
: dump16
|
||||
( addr u )
|
||||
0do
|
||||
dup hex4 [char] : emit space dup @ hex4 cr 2+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
: decimal d# 10 base ! ;
|
||||
: hex d# 16 base ! ;
|
||||
|
||||
: S.R ( a u n -- ) OVER - SPACES TYPE ;
|
||||
: D.R ( d n -- ) ( 8.6.1.1070 ) >R DUP >R DABS <# #S R> SIGN #> R> S.R ;
|
||||
: U.R ( u n -- ) ( 6.2.2330 ) d# 0 SWAP D.R ;
|
||||
: .R ( n n -- ) ( 6.2.0210 ) >R S>D R> D.R ;
|
||||
|
||||
: D. ( d -- ) ( 8.6.1.1060 ) d# 0 D.R SPACE ;
|
||||
: U. ( u -- ) ( 6.1.2320 ) d# 0 D. ;
|
||||
: . ( n -- ) ( 6.1.0180 ) BASE @ d# 10 XOR IF U. EXIT THEN S>D D. ;
|
||||
: ? ( a -- ) ( 15.6.1.0600 ) @ . ;
|
||||
|
||||
( Numeric input )
|
||||
|
||||
: DIGIT? ( c base -- u f ) ( 0xA3 )
|
||||
>R [CHAR] 0 - D# 9 OVER <
|
||||
IF D# 7 - DUP D# 10 < OR THEN DUP R> U< ;
|
||||
|
||||
: >number ( ud a u -- ud a u ) ( 6.1.0570 )
|
||||
begin
|
||||
dup 0= if exit then
|
||||
over c@ base @ digit? if
|
||||
>r 2swap
|
||||
drop base @ um*
|
||||
r> s>d d+ 2swap
|
||||
d# 1 /string >number
|
||||
else
|
||||
drop exit
|
||||
then
|
||||
again
|
||||
;
|
||||
|
||||
: .s
|
||||
[char] < emit
|
||||
depth dup hex2
|
||||
[char] > emit
|
||||
|
||||
d# 8 min
|
||||
?dup if
|
||||
0do
|
||||
i pick hex4 space
|
||||
loop
|
||||
then
|
||||
;
|
||||
|
||||
build-debug? [IF]
|
||||
: (assert)
|
||||
s" **** ASSERTION FAILED **** " type
|
||||
;fallthru
|
||||
: (snap)
|
||||
type space
|
||||
s" LINE " type
|
||||
.
|
||||
[char] : emit
|
||||
space
|
||||
.s
|
||||
cr
|
||||
;
|
||||
[THEN]
|
||||
|
||||
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
: endian dup d# 8 lshift swap d# 8 rshift or ;
|
||||
: 2endian endian swap endian ;
|
||||
: swab endian ;
|
||||
: typepad ( c-addr u w ) over - >r type r> spaces ;
|
||||
: even? d# 1 and 0= ;
|
||||
|
||||
\ rise? and fall? act like ! - except that they leave a true
|
||||
\ if the value rose or fell, respectively.
|
||||
|
||||
: rise? ( u a -- f ) 2dup @ u> >r ! r> ;
|
||||
: fall? ( u a -- f ) 2dup @ u< >r ! r> ;
|
||||
|
||||
]module
|
||||
11
j1/firmware/packet.fs
Normal file
11
j1/firmware/packet.fs
Normal file
@ -0,0 +1,11 @@
|
||||
( Packet construction, tx, rx JCB 13:25 08/24/10)
|
||||
module[ packet"
|
||||
|
||||
: packet@ ( u -- u )
|
||||
mac-inoffset mac@ ;
|
||||
|
||||
: packetd@ ( u -- ud )
|
||||
mac-inoffset dup 2+ mac@ swap mac@ ;
|
||||
|
||||
|
||||
]module
|
||||
434
j1/firmware/ps2kb.fs
Normal file
434
j1/firmware/ps2kb.fs
Normal file
@ -0,0 +1,434 @@
|
||||
( PS/2 keyboard handler JCB 18:29 11/21/10)
|
||||
|
||||
================================================================
|
||||
|
||||
Keycodes represent raw keypresses. Need to map these to
|
||||
ASCII characters. Each key can generate several ASCII
|
||||
codes depending on the state of the SHIFT/CTRL keys.
|
||||
|
||||
Could use table giving keycode->ascii, but most keys
|
||||
generate two codes, so would need word for each.
|
||||
Keycodes 00-83. Storage 262 bytes.
|
||||
|
||||
Table of N ascii codes, each entry specifies a keycode
|
||||
and shift state
|
||||
|
||||
================================================================
|
||||
|
||||
module[ ps2kb"
|
||||
|
||||
meta
|
||||
|
||||
create asciikb 144 allot
|
||||
asciikb 144 erase
|
||||
|
||||
\ 1 word for each key.
|
||||
\ if high bit is zero, then
|
||||
|
||||
h# 84 constant nscancodes
|
||||
create scanmap nscancodes cells allot
|
||||
scanmap nscancodes cells 2constant scanmap_
|
||||
scanmap_ erase
|
||||
|
||||
: scanmap! ( n u -- ) \ write n to cell u in scanmap
|
||||
cells scanmap + !
|
||||
;
|
||||
|
||||
\ knowkey plain xx f0xx
|
||||
\ knowkey-n plain 3x, yy numlock exyy
|
||||
\ knowkey-h shift mask yy d0yy
|
||||
\ knowkey-s plain xx, shifted^caps yy xxyy
|
||||
|
||||
h# f000 constant plainmask
|
||||
h# e000 constant numlockmask
|
||||
h# d000 constant shiftmask
|
||||
|
||||
: wordval bl word count evaluate ;
|
||||
|
||||
: knowkey
|
||||
wordval
|
||||
plainmask or
|
||||
swap scanmap!
|
||||
;
|
||||
: knowkey-s
|
||||
\ dup char asciikb + c!
|
||||
\ 128 or
|
||||
\ char asciikb + c!
|
||||
char 8 lshift char or
|
||||
swap scanmap!
|
||||
;
|
||||
: knowkey-h
|
||||
wordval shiftmask or
|
||||
swap scanmap!
|
||||
;
|
||||
: knowkey-n
|
||||
\ dup char asciikb + c!
|
||||
\ 128 or
|
||||
\ char asciikb + c!
|
||||
char [char] . - 8 lshift wordval or
|
||||
numlockmask or
|
||||
swap scanmap!
|
||||
;
|
||||
|
||||
h# 01 constant SHIFTL
|
||||
h# 02 constant SHIFTR
|
||||
h# 04 constant CONTROL
|
||||
h# 08 constant ALT
|
||||
char * constant ASTERISK
|
||||
char - constant MINUS
|
||||
char + constant PLUS
|
||||
char 5 constant FIVE
|
||||
|
||||
include keycodes.fs
|
||||
|
||||
h# 76 knowkey ESC
|
||||
h# 05 knowkey KF1
|
||||
h# 06 knowkey KF2
|
||||
h# 04 knowkey KF3
|
||||
h# 0c knowkey KF4
|
||||
h# 03 knowkey KF5
|
||||
h# 0b knowkey KF6
|
||||
h# 83 knowkey KF7
|
||||
h# 0a knowkey KF8
|
||||
h# 01 knowkey KF9
|
||||
h# 09 knowkey KF10
|
||||
h# 78 knowkey KF11
|
||||
h# 07 knowkey KF12
|
||||
|
||||
h# 0e knowkey-s ` ~
|
||||
h# 16 knowkey-s 1 !
|
||||
h# 1e knowkey-s 2 @
|
||||
h# 26 knowkey-s 3 #
|
||||
h# 25 knowkey-s 4 $
|
||||
h# 2e knowkey-s 5 %
|
||||
h# 36 knowkey-s 6 ^
|
||||
h# 3d knowkey-s 7 &
|
||||
h# 3e knowkey-s 8 *
|
||||
h# 46 knowkey-s 9 (
|
||||
h# 45 knowkey-s 0 )
|
||||
h# 4e knowkey-s - _
|
||||
h# 55 knowkey-s = +
|
||||
h# 5d knowkey-s \ |
|
||||
h# 66 knowkey KDEL
|
||||
|
||||
h# 0d knowkey TAB
|
||||
h# 15 knowkey-s q Q
|
||||
h# 1d knowkey-s w W
|
||||
h# 24 knowkey-s e E
|
||||
h# 2d knowkey-s r R
|
||||
h# 2c knowkey-s t T
|
||||
h# 35 knowkey-s y Y
|
||||
h# 3c knowkey-s u U
|
||||
h# 43 knowkey-s i I
|
||||
h# 44 knowkey-s o O
|
||||
h# 4d knowkey-s p P
|
||||
h# 54 knowkey-s [ {
|
||||
h# 5b knowkey-s ] }
|
||||
h# 5a knowkey ENTER
|
||||
|
||||
h# 58 knowkey -1
|
||||
h# 1c knowkey-s a A
|
||||
h# 1b knowkey-s s S
|
||||
h# 23 knowkey-s d D
|
||||
h# 2b knowkey-s f F
|
||||
h# 34 knowkey-s g G
|
||||
h# 33 knowkey-s h H
|
||||
h# 3b knowkey-s j J
|
||||
h# 42 knowkey-s k K
|
||||
h# 4b knowkey-s l L
|
||||
h# 4c knowkey-s ; :
|
||||
h# 52 knowkey-s ' "
|
||||
|
||||
h# 1a knowkey-s z Z
|
||||
h# 22 knowkey-s x X
|
||||
h# 21 knowkey-s c C
|
||||
h# 2a knowkey-s v V
|
||||
h# 32 knowkey-s b B
|
||||
h# 31 knowkey-s n N
|
||||
h# 3a knowkey-s m M
|
||||
h# 41 knowkey-s , <
|
||||
h# 49 knowkey-s . >
|
||||
h# 4a knowkey-s / ?
|
||||
|
||||
h# 29 knowkey BL
|
||||
|
||||
h# 12 knowkey-h SHIFTL
|
||||
h# 59 knowkey-h SHIFTR
|
||||
h# 14 knowkey-h CONTROL
|
||||
h# 11 knowkey-h ALT
|
||||
|
||||
h# 70 knowkey-n 0 KINS
|
||||
h# 71 knowkey-n . KDEL
|
||||
h# 69 knowkey-n 1 KEND
|
||||
h# 72 knowkey-n 2 KDOWN
|
||||
h# 7a knowkey-n 3 KPGDN
|
||||
h# 6b knowkey-n 4 KLEFT
|
||||
h# 73 knowkey FIVE
|
||||
h# 74 knowkey-n 6 KRIGHT
|
||||
h# 6c knowkey-n 7 KHOME
|
||||
h# 75 knowkey-n 8 KUP
|
||||
h# 7d knowkey-n 9 KPGUP
|
||||
h# 77 knowkey -2
|
||||
h# 7c knowkey ASTERISK
|
||||
h# 7b knowkey MINUS
|
||||
h# 79 knowkey PLUS
|
||||
|
||||
: t,c ( c-addr u -- ) \ compile u cells into target memory
|
||||
0 do
|
||||
dup @ t, cell+
|
||||
loop
|
||||
drop
|
||||
;
|
||||
|
||||
target create scanmap meta
|
||||
scanmap nscancodes t,c
|
||||
|
||||
target
|
||||
|
||||
include keycodes.fs
|
||||
|
||||
: scanmap@ ( u - u ) \ return scanmap entry u
|
||||
cells scanmap + @ ;
|
||||
|
||||
variable kbread \ read ptr into 64-bit KB fifo
|
||||
variable kbstate \ accumulates 11-bit code
|
||||
|
||||
: ps2listening
|
||||
ps2_clk_dir in
|
||||
ps2_dat_dir in
|
||||
;
|
||||
: kbfifo@ ( u -- f ) \ read bit u from 64-bit KB fifo
|
||||
dup d# 4 rshift 2* kbfifo + @
|
||||
swap d# 15 and rshift d# 1 and
|
||||
;
|
||||
: kbnew ( -- ) \ start accumulating new code
|
||||
h# 800 kbstate !
|
||||
;
|
||||
: kbfifo-cold
|
||||
kbfifocount @ kbread !
|
||||
kbnew
|
||||
;
|
||||
: kbfifo-fullness ( -- u ) \ how many unread bits in the kbfifo
|
||||
kbfifocount @ kbread @ - h# ff and
|
||||
;
|
||||
|
||||
variable ps2_clk'
|
||||
: waitfall \ wait for falling edge on ps2_clk
|
||||
begin ps2_clk @ ps2_clk' fall? until ;
|
||||
|
||||
: ps2-out1 ( u -- ) \ send lsb of u to keyboard
|
||||
ps2_dat ! waitfall ;
|
||||
|
||||
: oddparity ( u1 -- u2 ) \ u2 is odd parity of u1
|
||||
dup d# 4 rshift xor
|
||||
dup d# 2 rshift xor
|
||||
dup 2/ xor
|
||||
;
|
||||
|
||||
: kb-request
|
||||
ps2_clk_dir out ps2_clk off \ clock low
|
||||
d# 60. sleepus
|
||||
ps2_dat_dir out ps2_dat off \ dat low
|
||||
ps2_clk_dir in \ release clock
|
||||
|
||||
begin ps2_clk @ until
|
||||
ps2_clk' on
|
||||
|
||||
\ bad keyboard hangs here
|
||||
false ps2-out1 \ start
|
||||
|
||||
dup
|
||||
d# 8 0do
|
||||
dup ps2-out1 2/
|
||||
loop
|
||||
drop
|
||||
|
||||
oddparity ps2-out1 \ parity
|
||||
true ps2-out1 \ stop
|
||||
|
||||
ps2listening \ waitfall
|
||||
kbfifo-cold
|
||||
;
|
||||
|
||||
: kbbit
|
||||
d# 11 lshift kbstate @ 2/ or
|
||||
kbstate !
|
||||
;
|
||||
: rawready? ( -- f) \ is the raw keycode ready?
|
||||
kbstate @ d# 1 and ;
|
||||
|
||||
: kbraw ( -- u ) \ get the current raw keycode
|
||||
kbstate @ d# 2 rshift h# ff and
|
||||
kbnew
|
||||
;
|
||||
|
||||
variable lock
|
||||
|
||||
: rawloop
|
||||
begin
|
||||
kbfifocount @ lock !
|
||||
kbfifo-fullness 0<>
|
||||
rawready? 0= and
|
||||
while
|
||||
kbfifo-fullness 1- kbfifo@
|
||||
kbfifocount @ lock @ = if
|
||||
kbbit d# 1 kbread +!
|
||||
else
|
||||
drop
|
||||
then
|
||||
repeat
|
||||
;
|
||||
|
||||
: oneraw
|
||||
begin
|
||||
rawloop
|
||||
rawready?
|
||||
until
|
||||
kbraw
|
||||
;
|
||||
|
||||
: >leds ( u -- ) \ set keyboard leds (CAPS NUM SCROLL)
|
||||
h# ed kb-request
|
||||
oneraw drop
|
||||
kb-request
|
||||
;
|
||||
|
||||
( Decoding JCB 19:25 12/04/10)
|
||||
|
||||
variable capslock
|
||||
variable numlock
|
||||
variable isrelease \ is this is key release
|
||||
variable ise0 \ is this an E0-prefix key
|
||||
0 value mods \ bitmask of modifier keys
|
||||
\ RALT RCTRL -- -- LALT LCTRL RSHIFT LSHIFT
|
||||
|
||||
: lrshift? ( -- f ) \ is either shift pressed?
|
||||
mods h# 03 and ;
|
||||
: lrcontrol?
|
||||
mods h# 44 and ;
|
||||
: lralt?
|
||||
mods h# 88 and ;
|
||||
|
||||
variable curkey
|
||||
|
||||
: append ( u -- ) \ join u with mods write to curkey
|
||||
h# ff and mods d# 8 lshift or
|
||||
curkey !
|
||||
;
|
||||
|
||||
: shiftmask
|
||||
h# ff and
|
||||
ise0 @ if d# 4 lshift then
|
||||
;
|
||||
: shift-press ( u -- ) \ a shift key was pressed
|
||||
shiftmask mods or to mods ;
|
||||
: shift-release ( u -- ) \ a shift key was released
|
||||
shiftmask invert mods and to mods ;
|
||||
|
||||
: shiftable-press ( u -- ) \ a shiftable key was pressed
|
||||
mods d# 3 and 0= capslock @ xor if
|
||||
d# 8 rshift
|
||||
then
|
||||
append
|
||||
;
|
||||
: ignore drop ;
|
||||
|
||||
: myleds \ compute led values from caps/numlock, send to KB
|
||||
numlock @ d# 2 and
|
||||
capslock @ d# 4 and
|
||||
or
|
||||
>leds
|
||||
;
|
||||
|
||||
: toggle ( a -- ) \ invert cell at a
|
||||
dup @ invert swap ! ;
|
||||
|
||||
: plain-press ( u -- )
|
||||
dup d# -1 = if
|
||||
drop capslock toggle myleds
|
||||
else
|
||||
dup d# -2 = if
|
||||
drop numlock toggle myleds
|
||||
else
|
||||
append
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
: num-press
|
||||
\ if e0 prefix, low code, else hi code or 30
|
||||
\ e0 numlock
|
||||
\ 0 0 cursor
|
||||
\ 0 1 num
|
||||
\ 1 0 cursor
|
||||
\ 1 1 cursor
|
||||
ise0 @ 0= numlock @ and if
|
||||
d# 8 rshift h# f and [char] . +
|
||||
then
|
||||
append
|
||||
;
|
||||
|
||||
jumptable keyhandler
|
||||
\ PRESS RELEASE
|
||||
( 0 ) | shiftable-press | ignore
|
||||
( d ) | shift-press | shift-release
|
||||
( e ) | num-press | ignore
|
||||
( f ) | plain-press | ignore
|
||||
|
||||
: handle-raw ( u -- )
|
||||
dup h# e0 = if
|
||||
drop ise0 on
|
||||
else
|
||||
dup h# f0 = if
|
||||
drop isrelease on
|
||||
else
|
||||
dup h# 84 < if
|
||||
scanmap@
|
||||
\ hi 4 bits,
|
||||
\ 1100 -> 0
|
||||
\ 1101 -> 1
|
||||
\ 1110 -> 2
|
||||
\ 1111 -> 3
|
||||
\
|
||||
dup d# 12 rshift d# 12 - d# 0 max
|
||||
|
||||
2* isrelease @ + keyhandler execute
|
||||
|
||||
isrelease off
|
||||
ise0 off
|
||||
else
|
||||
drop
|
||||
then
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
( kb: high-level keyboard JCB 19:45 12/04/10)
|
||||
|
||||
: kb-cold
|
||||
ps2listening kbfifo-cold
|
||||
h# 7 >leds
|
||||
sleep.1
|
||||
h# 0 >leds
|
||||
|
||||
numlock off
|
||||
capslock off
|
||||
curkey off
|
||||
;
|
||||
|
||||
: kbfifo-proc
|
||||
rawloop
|
||||
rawready? if
|
||||
kbraw handle-raw
|
||||
then
|
||||
;
|
||||
|
||||
: key? ( -- flag )
|
||||
kbfifo-proc
|
||||
curkey @ 0<> ;
|
||||
: key ( -- u )
|
||||
begin key? until
|
||||
curkey @ curkey off ;
|
||||
|
||||
]module
|
||||
|
||||
36
j1/firmware/sincos.fs
Normal file
36
j1/firmware/sincos.fs
Normal file
@ -0,0 +1,36 @@
|
||||
( Sine and cosine JCB 18:29 11/18/10)
|
||||
|
||||
create sintab
|
||||
|
||||
meta
|
||||
|
||||
: mksin
|
||||
65 0 do
|
||||
i s>d d>f 128e0 f/ pi f* fsin
|
||||
32767e0 f* f>d drop
|
||||
t,
|
||||
loop
|
||||
;
|
||||
mksin
|
||||
|
||||
target
|
||||
|
||||
: sin ( th -- v )
|
||||
dup d# 128 and >r
|
||||
d# 127 and
|
||||
dup d# 63 > if
|
||||
invert d# 129 + \ 64->64, 65->63
|
||||
then
|
||||
cells sintab + @
|
||||
r> if
|
||||
negate
|
||||
then
|
||||
;
|
||||
|
||||
: cos d# 64 + sin ;
|
||||
|
||||
: sin* ( s th -- sinth * s )
|
||||
sin swap 2* m* nip ;
|
||||
|
||||
: cos* ( s th -- costh * s )
|
||||
cos swap 2* m* nip ;
|
||||
20
j1/firmware/sprite.fs
Normal file
20
j1/firmware/sprite.fs
Normal file
@ -0,0 +1,20 @@
|
||||
( Sprite low-level JCB 15:23 11/15/10)
|
||||
|
||||
: vga-line@
|
||||
begin
|
||||
vga_line @
|
||||
vga_line @
|
||||
over xor
|
||||
while
|
||||
drop
|
||||
repeat
|
||||
;
|
||||
|
||||
: waitblank begin vga-line@ d# 512 = until ;
|
||||
|
||||
: sprite! ( x y spr -- )
|
||||
2* cells vga_spritey + tuck ! 2- ! ;
|
||||
|
||||
: hide \ hide all the sprites at (800,800)
|
||||
d# 8 0do d# 800 dup i sprite! loop ;
|
||||
|
||||
67
j1/firmware/tftp.fs
Normal file
67
j1/firmware/tftp.fs
Normal file
@ -0,0 +1,67 @@
|
||||
( TFTP JCB 09:16 11/11/10)
|
||||
|
||||
variable blocknum
|
||||
|
||||
: tftp-ack ( -- )
|
||||
d# 2 ETH.IP.SRCIP mac-inoffset mac@n arp-lookup if
|
||||
ETH.IP.UDP.SOURCEPORT packet@
|
||||
d# 1077
|
||||
d# 2 ETH.IP.SRCIP mac-inoffset mac@n
|
||||
net-my-ip
|
||||
2over arp-lookup
|
||||
( dst-port src-port dst-ip src-ip *ethaddr )
|
||||
udp-header
|
||||
d# 4 mac-pkt-,
|
||||
blocknum @ mac-pkt-,
|
||||
udp-wrapup mac-send
|
||||
then
|
||||
;
|
||||
|
||||
: tftp-handler ( -- )
|
||||
IP_PROTO_UDP ip-isproto if
|
||||
OFFSET_UDP_DESTPORT packet@ d# 69 = if
|
||||
udp-checksum? if
|
||||
ETH.IP.UDP.TFTP.OPCODE packet@
|
||||
s" tftp opcode=" type dup hex4 cr
|
||||
dup d# 2 = if
|
||||
s" WRQ filename: " type
|
||||
ETH.IP.UDP.TFTP.RWRQ.FILENAME mac-inoffset d# 32 mac-dump
|
||||
|
||||
d# 0 blocknum !
|
||||
tftp-ack
|
||||
then
|
||||
drop
|
||||
then
|
||||
then
|
||||
OFFSET_UDP_DESTPORT packet@ d# 1077 = if
|
||||
udp-checksum? if
|
||||
ETH.IP.UDP.TFTP.OPCODE packet@
|
||||
s" tftp opcode=" type dup hex4 cr
|
||||
dup d# 3 = if
|
||||
s" tftp recv=" type ETH.IP.UDP.TFTP.DATA.BLOCK packet@ hex4 s" expected=" type blocknum @ 1+ hex4 cr
|
||||
blocknum @ 1+
|
||||
ETH.IP.UDP.TFTP.DATA.BLOCK packet@ = if
|
||||
\ data at ETH.IP.UDP.TFTP.DATA.DATA
|
||||
ETH.IP.UDP.TFTP.DATA.DATA mac-inoffset
|
||||
blocknum @ d# 9 lshift h# 2000 +
|
||||
d# 256 0do
|
||||
over mac@ h# 5555 xor over h# 3ffe min !
|
||||
2+ swap 2+ swap
|
||||
loop
|
||||
2drop
|
||||
d# 1 blocknum +!
|
||||
tftp-ack
|
||||
ETH.IP.UDP.LENGTH packet@ d# 12 - 0= if
|
||||
h# 2000 h# 100 dump
|
||||
bootloader
|
||||
then
|
||||
else
|
||||
s" unexpected blocknum" type cr
|
||||
tftp-ack
|
||||
then
|
||||
then
|
||||
drop
|
||||
then
|
||||
then
|
||||
then
|
||||
;
|
||||
33
j1/firmware/time.fs
Normal file
33
j1/firmware/time.fs
Normal file
@ -0,0 +1,33 @@
|
||||
( Time access JCB 13:27 08/24/10)
|
||||
|
||||
variable prevth \ previous high time
|
||||
2variable timeh \ high 32 bits of time
|
||||
|
||||
: time@ ( -- time. )
|
||||
begin
|
||||
time 2@
|
||||
time 2@
|
||||
2over d<>
|
||||
while
|
||||
2drop
|
||||
repeat
|
||||
|
||||
\ dup prevth fall? if
|
||||
\ d# 1. timeh d+!
|
||||
\ then
|
||||
;
|
||||
|
||||
: timeq ( -- d d ) \ 64-bit time
|
||||
time@ timeh 2@ ;
|
||||
|
||||
: setalarm ( d a -- ) \ set alarm a for d microseconds hence
|
||||
>r time@ d+ r> 2! ;
|
||||
: isalarm ( a -- f )
|
||||
2@ time@ d- d0<= ;
|
||||
|
||||
2variable sleeper
|
||||
: sleepus sleeper setalarm begin sleeper isalarm until ;
|
||||
: sleep.1 d# 100000. sleepus ;
|
||||
: sleep1 d# 1000000. sleepus ;
|
||||
|
||||
: took ( d -- ) time@ 2swap d- s" took " type d. cr ;
|
||||
311
j1/firmware/twist.py
Normal file
311
j1/firmware/twist.py
Normal file
@ -0,0 +1,311 @@
|
||||
from twisted.internet.protocol import DatagramProtocol
|
||||
from twisted.internet import reactor, task
|
||||
from twisted.internet.task import deferLater
|
||||
|
||||
import os
|
||||
import time
|
||||
import struct
|
||||
import sys
|
||||
import hashlib
|
||||
import operator
|
||||
import functools
|
||||
import random
|
||||
|
||||
class Transporter(DatagramProtocol):
|
||||
|
||||
def __init__(self, jobs):
|
||||
self.udp_transport = reactor.listenUDP(9947, self)
|
||||
self.pending = {}
|
||||
self.seq = 0
|
||||
self.jobs = jobs
|
||||
self.firstjob()
|
||||
task.LoopingCall(self.earliest).start(0.1)
|
||||
reactor.run()
|
||||
|
||||
def firstjob(self):
|
||||
self.jobs[0].startwork(self)
|
||||
|
||||
def propose(self, cmd, rest):
|
||||
seq = self.seq
|
||||
self.seq += 1
|
||||
data = struct.pack(">HH", seq, cmd) + rest;
|
||||
self.pending[seq] = (time.time(), data)
|
||||
return seq
|
||||
|
||||
def earliest(self):
|
||||
bytime = [(t, k) for (k, (t, _)) in self.pending.items()]
|
||||
for (t, seq) in sorted(bytime)[:32]:
|
||||
self.send(seq)
|
||||
self.pending[seq] = (time.time(), self.pending[seq][1])
|
||||
|
||||
def datagramReceived(self, data, (host, port)):
|
||||
# print "received %r from %s:%d" % (data, host, port)
|
||||
(opcode, seq) = struct.unpack(">HH", data[:4])
|
||||
assert opcode == 0
|
||||
if seq in self.pending:
|
||||
del self.pending[seq]
|
||||
try:
|
||||
self.jobs[0].addresult(self, seq, data[4:])
|
||||
except AssertionError as e:
|
||||
print 'assertion failed', e
|
||||
reactor.stop()
|
||||
return
|
||||
print "ACK ", seq, "pending", len(self.pending)
|
||||
if len(self.pending) == 0:
|
||||
self.jobs[0].close()
|
||||
self.jobs = self.jobs[1:]
|
||||
if self.jobs != []:
|
||||
self.firstjob()
|
||||
else:
|
||||
reactor.stop()
|
||||
# self.transport.write(data, (host, port))
|
||||
|
||||
def send(self, seq):
|
||||
(_, data) = self.pending[seq]
|
||||
# print "send %r" % data
|
||||
self.udp_transport.write(data, ("192.168.0.99", 947))
|
||||
|
||||
def addresult(self, seq, payload):
|
||||
pass
|
||||
|
||||
|
||||
class Action(object):
|
||||
def addresult(self, tr, seq, payload):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
class ReadRAM(Action):
|
||||
|
||||
def startwork(self, tr):
|
||||
self.result = 16384 * [None]
|
||||
self.seqs = {}
|
||||
for i in range(0, 128):
|
||||
self.seqs[tr.propose(0, struct.pack(">H", i * 128))] = i * 128
|
||||
|
||||
def addresult(self, tr, seq, payload):
|
||||
addr = self.seqs[seq]
|
||||
assert len(payload) == 128
|
||||
for i in range(128):
|
||||
self.result[addr + i] = ord(payload[i])
|
||||
|
||||
def close(self):
|
||||
for a in range(0, 16384, 16):
|
||||
print ("%04x " % a) + " ".join("%02x" % x for x in self.result[a:a+16])
|
||||
|
||||
|
||||
class WriteRAM(Action):
|
||||
|
||||
def startwork(self, tr):
|
||||
code = open('j1.bin').read()
|
||||
for i in range(0x1f80 / 128):
|
||||
print i
|
||||
o = 128 * i
|
||||
tr.propose(1, struct.pack(">H128s", 0x2000 + o, code[o:o+128]))
|
||||
|
||||
class VerifyRAM(ReadRAM):
|
||||
def close(self):
|
||||
actual = "".join([chr(c) for c in self.result[0x2000:]])
|
||||
expected = open('j1.bin').read()
|
||||
l = 0x1f80
|
||||
assert actual[:l] == expected[:l]
|
||||
|
||||
class Reboot(Action):
|
||||
def startwork(self, tr):
|
||||
tr.propose(2, "")
|
||||
|
||||
class ReadFlash(Action):
|
||||
|
||||
def startwork(self, tr):
|
||||
self.result = 2 * 1024 * 1024 * [None]
|
||||
self.seqs = {}
|
||||
for addr in range(0, len(self.result), 128):
|
||||
self.seqs[tr.propose(3, struct.pack(">I", addr))] = addr
|
||||
|
||||
def addresult(self, tr, seq, payload):
|
||||
addr = self.seqs[seq]
|
||||
assert len(payload) == 128
|
||||
for i in range(128):
|
||||
self.result[addr + i] = ord(payload[i])
|
||||
|
||||
def close(self):
|
||||
open('flash.dump', 'w').write("".join([chr(x) for x in self.result]))
|
||||
for a in range(0, 256, 16):
|
||||
print ("%04x " % a) + " ".join("%02x" % x for x in self.result[a:a+16])
|
||||
|
||||
class EraseFlash(Action):
|
||||
def startwork(self, tr):
|
||||
tr.propose(4, "")
|
||||
def close(self):
|
||||
time.sleep(5)
|
||||
|
||||
class WaitFlash(Action):
|
||||
def startwork(self, tr):
|
||||
self.seq = tr.propose(5, struct.pack(">I", 0))
|
||||
def addresult(self, tr, seq, payload):
|
||||
(res,) = struct.unpack(">H", payload)
|
||||
if res == 0:
|
||||
self.startwork(tr)
|
||||
|
||||
def bitload(bitfilename):
|
||||
bit = open(bitfilename, "r")
|
||||
|
||||
def getH(fi):
|
||||
return struct.unpack(">H", bit.read(2))[0]
|
||||
def getI(fi):
|
||||
return struct.unpack(">I", bit.read(4))[0]
|
||||
|
||||
bit.seek(getH(bit), os.SEEK_CUR)
|
||||
assert getH(bit) == 1
|
||||
|
||||
# Search for the data section in the .bit file...
|
||||
while True:
|
||||
ty = ord(bit.read(1))
|
||||
if ty == 0x65:
|
||||
break
|
||||
length = getH(bit)
|
||||
bit.seek(length, os.SEEK_CUR)
|
||||
fieldLength = getI(bit)
|
||||
return bit.read(fieldLength)
|
||||
|
||||
# open("xxx", "w").write(bitload("j1_program.bit"))
|
||||
|
||||
import intelhex
|
||||
import array
|
||||
|
||||
class Hexfile(object):
|
||||
def __init__(self, filename):
|
||||
self.hf = intelhex.IntelHex(filename)
|
||||
self.hf.readfile()
|
||||
while (self.hf.maxaddr() % 128) != 127:
|
||||
self.hf[self.hf.maxaddr() + 1] = 0xff
|
||||
print "%x %x" % (self.hf.minaddr(), self.hf.maxaddr())
|
||||
|
||||
def minmax(self):
|
||||
return (self.hf.minaddr(), self.hf.maxaddr())
|
||||
|
||||
# The XESS CPLD bootloader runs the flash in byte mode,
|
||||
# and the flash is littleendian, so must do the endian
|
||||
# swap here
|
||||
def blk(self, o):
|
||||
b128 = array.array('B', [self.hf[o + i] for i in range(128)]).tostring()
|
||||
hh = array.array('H', b128)
|
||||
hh.byteswap()
|
||||
return hh.tostring()
|
||||
|
||||
class WriteFlash(Action, Hexfile):
|
||||
|
||||
def startwork(self, tr):
|
||||
for o in range(self.hf.minaddr(), self.hf.maxaddr(), 128):
|
||||
tr.propose(6, struct.pack(">I", o) + self.blk(o))
|
||||
|
||||
class VerifyFlash(Action, Hexfile):
|
||||
|
||||
def startwork(self, tr):
|
||||
self.seqs = {}
|
||||
for o in range(self.hf.minaddr(), self.hf.maxaddr(), 128):
|
||||
self.seqs[tr.propose(3, struct.pack(">I", o))] = o
|
||||
|
||||
def addresult(self, tr, seq, payload):
|
||||
addr = self.seqs[seq]
|
||||
assert len(payload) == 128, 'short packet'
|
||||
assert self.blk(addr) == payload, "mismatch at %#x" % addr
|
||||
|
||||
def close(self):
|
||||
print "Flash verified OK"
|
||||
|
||||
class EraseSector(Action):
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
def startwork(self, tr):
|
||||
tr.propose(7, struct.pack(">I", self.a))
|
||||
def close(self):
|
||||
time.sleep(.1)
|
||||
|
||||
class WaitSector(Action):
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
def startwork(self, tr):
|
||||
self.seq = tr.propose(5, struct.pack(">I", self.a))
|
||||
def addresult(self, tr, seq, payload):
|
||||
(res,) = struct.unpack(">H", payload)
|
||||
if res == 0:
|
||||
self.startwork(tr)
|
||||
|
||||
class LoadSector(Action):
|
||||
def __init__(self, a, data):
|
||||
self.a = a
|
||||
self.data = data
|
||||
def startwork(self, tr):
|
||||
for o in range(0, len(self.data), 128):
|
||||
blk = self.data[o:o+128]
|
||||
if blk != (128 * chr(0xff)):
|
||||
tr.propose(6, struct.pack(">I", self.a + o) + blk)
|
||||
|
||||
class DumpSector(Action):
|
||||
|
||||
def __init__(self, a):
|
||||
self.a = a
|
||||
def startwork(self, tr):
|
||||
self.seqs = {}
|
||||
for o in [0]:
|
||||
self.seqs[tr.propose(3, struct.pack(">I", self.a + o))] = o
|
||||
|
||||
def addresult(self, tr, seq, payload):
|
||||
addr = self.a + self.seqs[seq]
|
||||
assert len(payload) == 128
|
||||
print "result", repr(payload)
|
||||
|
||||
# t = Transporter([WriteRAM(), VerifyRAM(), Reboot()])
|
||||
# t = Transporter([EraseFlash(), WaitFlash()])
|
||||
# sys.exit(0)
|
||||
|
||||
erasing = [EraseFlash(), WaitFlash()]
|
||||
bases = [ 0 ]
|
||||
bases = [0, 0x80000, 0x100000, 0x180000]
|
||||
bases = [0x80000]
|
||||
# Transporter(erasing + [WriteFlash("j1_program_%x.mcs" % base) for base in bases])
|
||||
# Transporter([VerifyFlash("j1_program_%x.mcs" % base) for base in bases])
|
||||
# Transporter([EraseSector(seca), WaitSector(seca), ld, DumpSector(seca)])
|
||||
|
||||
def loadcode(dsta, filenames):
|
||||
data = "".join([open(fn).read() for fn in filenames])
|
||||
return [EraseSector(dsta),
|
||||
WaitSector(dsta),
|
||||
LoadSector(dsta, data)]
|
||||
|
||||
def pngstr(filename):
|
||||
import Image
|
||||
sa = array.array('B', Image.open(filename).convert("L").tostring())
|
||||
return struct.pack('>1024H', *sa.tolist())
|
||||
|
||||
def erasesecs(lo, hi):
|
||||
r = []
|
||||
for s in range(lo, hi, 65536):
|
||||
r += [EraseSector(s), WaitSector(s)]
|
||||
return r
|
||||
|
||||
def loadhex(filename):
|
||||
w = WriteFlash(filename)
|
||||
(lo, hi) = w.minmax()
|
||||
return erasesecs(lo, hi) + [w]
|
||||
|
||||
def loadsprites(dsta, filenames):
|
||||
data = "".join([pngstr(f) for f in filenames])
|
||||
print "Loading %d bytes" % len(data)
|
||||
return erasesecs(dsta, dsta + len(data)) + [LoadSector(dsta, data)]
|
||||
|
||||
# Transporter(loadcode(0x180000, ["j1.png.pic", "font8x8", "j1.png.chr"]) + [Reboot()])
|
||||
spr = ["%d.png" % (i/2) for i in range(16)]
|
||||
spr += ["blob.png"] * 16
|
||||
spr += ["fsm-32.png", "pop.png"] * 6 + ["bomb.png", "pop.png", "shot.png", "pop.png"]
|
||||
|
||||
# Transporter(loadsprites(0x200000, spr))
|
||||
# Transporter(loadcode(0x190000, ["j1.bin"]) + [Reboot()])
|
||||
# t = Transporter([ReadFlash()])
|
||||
|
||||
Transporter(
|
||||
# loadhex("j1_program_80000.mcs")
|
||||
loadcode(0x190000, ["j1.bin"]) + [Reboot()]
|
||||
)
|
||||
41
j1/firmware/udp.fs
Normal file
41
j1/firmware/udp.fs
Normal file
@ -0,0 +1,41 @@
|
||||
( UDP header and wrapup JCB 13:22 08/24/10)
|
||||
|
||||
: udp-header ( dst-port src-port dst-ip src-ip *ethaddr -- )
|
||||
h# 11 ip-header
|
||||
mac-pkt-, \ src port
|
||||
mac-pkt-, \ dst port
|
||||
d# 2 mac-pkt-,0 \ length and checksum
|
||||
;
|
||||
|
||||
variable packetbase
|
||||
: packet packetbase @ + ;
|
||||
|
||||
: udp-checksum ( addr -- u ) \ compute UDP checksum on packet
|
||||
packetbase !
|
||||
ETH.IP.UDP.LENGTH packet @ d# 1 and if
|
||||
ETH.IP.UDP ETH.IP.UDP.LENGTH packet @ + packet
|
||||
dup @ h# ff00 and swap !
|
||||
then
|
||||
ETH.IP.UDP packet
|
||||
ETH.IP.UDP.LENGTH packet @ 1+ 2/
|
||||
mac-checksum invert
|
||||
d# 4 ETH.IP.SRCIP packet mac@n
|
||||
+1c +1c +1c +1c
|
||||
IP_PROTO_UDP +1c
|
||||
ETH.IP.UDP.LENGTH packet @ +1c
|
||||
invert
|
||||
;
|
||||
|
||||
: udp-checksum? true ;
|
||||
\ incoming udp-checksum 0= ;
|
||||
|
||||
: udp-wrapup
|
||||
mac-pkt-complete dup
|
||||
ip-wrapup
|
||||
|
||||
OFFSET_UDP -
|
||||
OFFSET_UDP_LENGTH packetout-off mac!
|
||||
|
||||
\ outgoing udp-checksum ETH.IP.UDP.CHECKSUM packetout-off !
|
||||
;
|
||||
|
||||
2
j1/firmware/version.fs
Normal file
2
j1/firmware/version.fs
Normal file
@ -0,0 +1,2 @@
|
||||
: version s" 649:659M" ;
|
||||
: builddate d# 1291578086. d# -0800 ;
|
||||
9
j1/synth/Makefile
Normal file
9
j1/synth/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
project = j1
|
||||
vendor = xilinx
|
||||
family = spartan3s
|
||||
part = xc3s1000-4ft256
|
||||
top_module = top
|
||||
|
||||
vfiles = ../verilog/top.v ../verilog/j1.v ../verilog/ck_div.v ../verilog/uart.v
|
||||
|
||||
include xilinx.mk
|
||||
12
j1/synth/j1.bmm
Normal file
12
j1/synth/j1.bmm
Normal file
@ -0,0 +1,12 @@
|
||||
ADDRESS_SPACE jram RAMB16 [0x00020000:0x00023fff]
|
||||
BUS_BLOCK
|
||||
j1/ram[7].ram [15:14];
|
||||
j1/ram[6].ram [13:12];
|
||||
j1/ram[5].ram [11:10];
|
||||
j1/ram[4].ram [9:8];
|
||||
j1/ram[3].ram [7:6];
|
||||
j1/ram[2].ram [5:4];
|
||||
j1/ram[1].ram [3:2];
|
||||
j1/ram[0].ram [1:0];
|
||||
END_BUS_BLOCK;
|
||||
END_ADDRESS_SPACE;
|
||||
327
j1/synth/j1.ucf
Normal file
327
j1/synth/j1.ucf
Normal file
@ -0,0 +1,327 @@
|
||||
#####################################################
|
||||
#
|
||||
# XSA-3S1000 Board FPGA pin assignment constraints
|
||||
#
|
||||
#####################################################
|
||||
#
|
||||
# Clocks
|
||||
#
|
||||
net CLKA loc=T9 | IOSTANDARD = LVCMOS33 ; # 100MHz
|
||||
#net CLKB loc=P8 | IOSTANDARD = LVCMOS33 ; # 50MHz
|
||||
#net CLKC loc=R9 | IOSTANDARD = LVCMOS33 ; # ??Mhz
|
||||
#
|
||||
# Push button switches
|
||||
#
|
||||
#NET SW1_3_N loc=K2 | IOSTANDARD = LVCMOS33 ; # Flash Block select
|
||||
#NET SW1_4_N loc=J4 | IOSTANDARD = LVCMOS33 ; # Flash Block
|
||||
#NET SW2_N loc=E11 | IOSTANDARD = LVCMOS33 ; # active-low pushbutton
|
||||
#NET SW3_N loc=A13 | IOSTANDARD = LVCMOS33 ; # active-low pushbutton
|
||||
#
|
||||
# PS/2 Keyboard
|
||||
#
|
||||
net PS2_CLK loc=B16 | IOSTANDARD = LVCMOS33 ;
|
||||
net PS2_DAT loc=E13 | IOSTANDARD = LVCMOS33 ;
|
||||
#
|
||||
# VGA Outputs
|
||||
#
|
||||
NET VGA_BLUE<0> LOC=C9 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_BLUE<1> LOC=E7 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_BLUE<2> LOC=D5 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_GREEN<0> LOC=A8 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_GREEN<1> LOC=A5 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_GREEN<2> LOC=C3 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_RED<0> LOC=C8 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_RED<1> LOC=D6 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_RED<2> LOC=B1 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_HSYNC_N LOC=B7 | IOSTANDARD = LVCMOS33 ;
|
||||
NET VGA_VSYNC_N LOC=D8 | IOSTANDARD = LVCMOS33 ;
|
||||
#
|
||||
# Manually assign locations for the DCMs along the bottom of the FPGA
|
||||
# because PAR sometimes places them in opposing corners and that ruins the clocks.
|
||||
#
|
||||
#INST "u1/gen_dlls.dllint" LOC="DCM_X0Y0";
|
||||
#INST "u1/gen_dlls.dllext" LOC="DCM_X1Y0";
|
||||
|
||||
# Manually assign locations for the DCMs along the bottom of the FPGA
|
||||
# because PAR sometimes places them in opposing corners and that ruins the clocks.
|
||||
#INST "u2_dllint" LOC="DCM_X0Y0";
|
||||
#INST "u2_dllext" LOC="DCM_X1Y0";
|
||||
#
|
||||
# SDRAM memory pin assignments
|
||||
#
|
||||
#net SDRAM_clkfb loc=N8 | IOSTANDARD = LVCMOS33 ; # feedback SDRAM clock after PCB delays
|
||||
#net SDRAM_clkout loc=E10 | IOSTANDARD = LVCMOS33 ; # clock to SDRAM
|
||||
#net SDRAM_CKE loc=D7 | IOSTANDARD = LVCMOS33 ; # SDRAM clock enable
|
||||
#net SDRAM_CS_N loc=B8 | IOSTANDARD = LVCMOS33 ; # SDRAM chip-select
|
||||
#net SDRAM_RAS_N loc=A9 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_CAS_N loc=A10 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_WE_N loc=B10 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_DQMH loc=D9 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_DQML loc=C10 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<0> loc=B5 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<1> loc=A4 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<2> loc=B4 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<3> loc=E6 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<4> loc=E3 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<5> loc=C1 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<6> loc=E4 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<7> loc=D3 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<8> loc=C2 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<9> loc=A3 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<10> loc=B6 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<11> loc=C5 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_A<12> loc=C6 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<0> loc=C15 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<1> loc=D12 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<2> loc=A14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<3> loc=B13 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<4> loc=D11 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<5> loc=A12 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<6> loc=C11 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<7> loc=D10 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<8> loc=B11 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<9> loc=B12 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<10> loc=C12 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<11> loc=B14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<12> loc=D14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<13> loc=C16 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<14> loc=F12 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_D<15> loc=F13 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_BA<0> loc=A7 | IOSTANDARD = LVCMOS33 ;
|
||||
#net SDRAM_BA<1> loc=C7 | IOSTANDARD = LVCMOS33 ;
|
||||
#
|
||||
# Flash memory interface
|
||||
|
||||
net FLASH_A<0> LOC=N5 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<1> LOC=K14 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<2> LOC=K13 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<3> LOC=K12 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<4> LOC=L14 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<5> LOC=M16 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<6> LOC=L13 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<7> LOC=N16 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<8> LOC=N14 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<9> LOC=P15 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<10> LOC=R16 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<11> LOC=P14 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<12> LOC=P13 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<13> LOC=N12 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<14> LOC=T14 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<15> LOC=R13 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<16> LOC=N10 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<17> LOC=M14 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<18> LOC=K3 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_A<19> LOC=K4 | IOSTANDARD = LVCMOS33 ;
|
||||
|
||||
net FLASH_D<0> LOC=M11 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<1> LOC=N11 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<2> LOC=P10 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<3> LOC=R10 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<4> LOC=T7 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<5> LOC=R7 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<6> LOC=N6 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<7> LOC=M6 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<8> LOC=T4 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<9> LOC=R5 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<10> LOC=T5 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<11> LOC=P6 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<12> LOC=M7 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<13> LOC=R6 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<14> LOC=N7 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_D<15> LOC=P7 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_CE_N LOC=R4 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_OE_N LOC=P5 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_WE_N LOC=M13 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_BYTE_N LOC=T8 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_RDY LOC=L12 | IOSTANDARD = LVCMOS33 ;
|
||||
net FLASH_RST_N LOC=P16 | IOSTANDARD = LVCMOS33 ;
|
||||
|
||||
# FPGA Programming interface
|
||||
#
|
||||
#net FPGA_D<0> LOC=M11 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D0, S1, LED_C
|
||||
#net FPGA_D<1> LOC=N11 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D1, S7, LED_DP
|
||||
#net FPGA_D<2> LOC=P10 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D2, S4, LED_B
|
||||
#net FPGA_D<3> LOC=R10 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D3, S6, LED_A
|
||||
#net FPGA_D<4> LOC=T7 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D4, S5, LED_F
|
||||
#net FPGA_D<5> LOC=R7 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D5, S3, LED_G
|
||||
#net FPGA_D<6> LOC=N6 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D6, S2, LED_E
|
||||
#net FPGA_D<7> LOC=M6 | IOSTANDARD = LVCMOS33 ; # shared with FLASH_D7, S0, LED_D
|
||||
#net FPGA_CCLK LOC=T15 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_DONE LOC=R14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_INIT_N LOC=N9 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_PROG_N LOC=B3 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_TCK LOC=C14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_TDI LOC=A2 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_TDI_CSN LOC=R3 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_TDO LOC=A15 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_TDO_WRN LOC=T3 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_TMS LOC=C13 | IOSTANDARD = LVCMOS33 ;
|
||||
#net FPGA_TMS_BSY LOC=P9 | IOSTANDARD = LVCMOS33 ;
|
||||
#
|
||||
# Status LED
|
||||
#
|
||||
#net S<0> loc=M6 | IOSTANDARD = LVCMOS33 ; # FPGA_D7, LED_D
|
||||
#net S<1> loc=M11 | IOSTANDARD = LVCMOS33 ; # FPGA_D0, LED_C
|
||||
#net S<2> loc=N6 | IOSTANDARD = LVCMOS33 ; # FPGA_D6, LED_E
|
||||
#net S<3> loc=R7 | IOSTANDARD = LVCMOS33 ; # FPGA_D5, LED_G
|
||||
#net S<4> loc=P10 | IOSTANDARD = LVCMOS33 ; # FPGA_D2, LED_B
|
||||
#net S<5> loc=T7 | IOSTANDARD = LVCMOS33 ; # FPGA_D4, LED_F
|
||||
#net S<6> loc=R10 | IOSTANDARD = LVCMOS33 ; # FPGA_D3, LED_A
|
||||
#net S<7> loc=N11 | IOSTANDARD = LVCMOS33 ; # FPGA_D1, LED_DP
|
||||
#
|
||||
# Parallel Port
|
||||
#
|
||||
#net PPORT_load loc=N14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_clk loc=P15 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_din<0> loc=R16 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_din<1> loc=P14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_din<2> loc=P13 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_din<3> loc=N12 | IOSTANDARD = LVCMOS33 ;
|
||||
#
|
||||
#net PPORT_dout<0> loc=N5 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_dout<1> loc=K14 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_dout<2> loc=K13 | IOSTANDARD = LVCMOS33 ;
|
||||
#net PPORT_dout<3> loc=T10 | IOSTANDARD = LVCMOS33 ;
|
||||
#
|
||||
#net PPORT_d<0> loc=N14 | IOSTANDARD = LVCMOS33 ; # FLASH_A<8> / PPORT_LOAD
|
||||
#net PPORT_d<1> loc=P15 | IOSTANDARD = LVCMOS33 ; # FLASH_A<9> / PPORT_CLK
|
||||
#net PPORT_d<2> loc=R16 | IOSTANDARD = LVCMOS33 ; # FLASH_A<10> / PPORT_DIN<0>
|
||||
#net PPORT_d<3> loc=P14 | IOSTANDARD = LVCMOS33 ; # FLASH_A<11> / PPORT_DIN<1>
|
||||
#net PPORT_d<4> loc=P13 | IOSTANDARD = LVCMOS33 ; # FLASH_A<12> / PPORT_DIN<2>
|
||||
#net PPORT_d<5> loc=N12 | IOSTANDARD = LVCMOS33 ; # FLASH_A<13> / PPORT_DIN<3>
|
||||
##net PPORT_d<6> loc=T14 | IOSTANDARD = LVCMOS33 ; # FLASH_A<14>
|
||||
##net PPORT_d<7> loc=R13 | IOSTANDARD = LVCMOS33 ; # FLASH_A<15>
|
||||
#
|
||||
#net PPORT_s<3> loc=N5 | IOSTANDARD = LVCMOS33 ; # FLASH_A<0> / PPORT_DOUT<0>
|
||||
#net PPORT_s<4> loc=K14 | IOSTANDARD = LVCMOS33 ; # FLASH_A<1> / PPORT_DOUT<1>
|
||||
#net PPORT_s<5> loc=K13 | IOSTANDARD = LVCMOS33 ; # FLASH_A<2> / PPORT_DOUT<2>
|
||||
#net PPORT_s<6> loc=T10 | IOSTANDARD = LVCMOS33 ; # / PPORT_DOUT<3>
|
||||
#
|
||||
########################################################
|
||||
#
|
||||
# XST3.0 pins
|
||||
#
|
||||
########################################################
|
||||
#
|
||||
# BAR LED
|
||||
#
|
||||
#net BAR<1> loc=L5 | IOSTANDARD = LVCMOS33 ; # bar led 1, PB_A0
|
||||
#net BAR<2> loc=N2 | IOSTANDARD = LVCMOS33 ; # bar led 2, PB_A1
|
||||
#net BAR<3> loc=M3 | IOSTANDARD = LVCMOS33 ; # bar led 3, PB_A2
|
||||
#net BAR<4> loc=N1 | IOSTANDARD = LVCMOS33 ; # bar led 4, PB_A3
|
||||
#net BAR<5> loc=T13 | IOSTANDARD = LVCMOS33 ; # bar led 5, PB_A4
|
||||
#net BAR<6> loc=L15 | IOSTANDARD = LVCMOS33 ; # bar led 6, ETHER_IRQ
|
||||
#net BAR<7> loc=J13 | IOSTANDARD = LVCMOS33 ; # bar led 7, USB_IRQ_N
|
||||
#net BAR<8> loc=H15 | IOSTANDARD = LVCMOS33 ; # bar led 8, IDE_IRQ
|
||||
#net BAR<9> loc=J16 | IOSTANDARD = LVCMOS33 ; # bar led 9, SLOT1_IRQ
|
||||
#net BAR<10> loc=J14 | IOSTANDARD = LVCMOS33 ; # bar led 10, SLOT2_IRQ
|
||||
#
|
||||
# Push Buttons
|
||||
#
|
||||
#net PB1_N loc=H4 | IOSTANDARD = LVCMOS33 ; # Shared with PB_D15
|
||||
#net PB2_N loc=L5 | IOSTANDARD = LVCMOS33 ; # Shared with BAR1, PB_A0
|
||||
#net PB3_N loc=N2 | IOSTANDARD = LVCMOS33 ; # Shared with BAR2, PB_A1
|
||||
#net PB4_N loc=M3 | IOSTANDARD = LVCMOS33 ; # Shared with BAR3, PB_A2
|
||||
#
|
||||
# RS232 PORT
|
||||
#
|
||||
net RS232_TXD loc=J2 | IOSTANDARD = LVCMOS33 ; # RS232 TD pin 3
|
||||
#net RS232_RXD loc=G5 | IOSTANDARD = LVCMOS33 ; # RS232 RD pin 2
|
||||
#net RS232_CTS loc=D1 | IOSTANDARD = LVCMOS33 ; # RS232 CTS
|
||||
#net RS232_RTS loc=F4 | IOSTANDARD = LVCMOS33 ; # RS232 RTS
|
||||
#
|
||||
# 16 Bit Peripheral Bus
|
||||
#
|
||||
# 5-bit Peripheral address bus
|
||||
net PB_A<0> loc=L5 | IOSTANDARD = LVCMOS33 ; # Shared with BAR1, PB2
|
||||
net PB_A<1> loc=N2 | IOSTANDARD = LVCMOS33 ; # Shared with BAR2, PB3
|
||||
net PB_A<2> loc=M3 | IOSTANDARD = LVCMOS33 ; # Shared with BAR3, PB4
|
||||
net PB_A<3> loc=N1 | IOSTANDARD = LVCMOS33 ; # Shared with BAR4
|
||||
net PB_A<4> loc=T13 | IOSTANDARD = LVCMOS33 ; # Shared with BAR5
|
||||
# 16-bit peripheral data bus
|
||||
net PB_D<0> loc=P12 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW1
|
||||
net PB_D<1> loc=J1 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW2
|
||||
net PB_D<2> loc=H1 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW3
|
||||
net PB_D<3> loc=H3 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW4
|
||||
net PB_D<4> loc=G2 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW5
|
||||
net PB_D<5> loc=K15 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW6
|
||||
net PB_D<6> loc=K16 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW7
|
||||
net PB_D<7> loc=F15 | IOSTANDARD = LVCMOS33 ; # Shared with DIPSW8
|
||||
net PB_D<8> loc=E2 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_A
|
||||
net PB_D<9> loc=E1 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_B
|
||||
net PB_D<10> loc=F3 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_C
|
||||
net PB_D<11> loc=F2 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_D
|
||||
net PB_D<12> loc=G4 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_E
|
||||
net PB_D<13> loc=G3 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_F
|
||||
net PB_D<14> loc=G1 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_G
|
||||
net PB_D<15> loc=H4 | IOSTANDARD = LVCMOS33 ; # Shared with LED2_DP, PB1
|
||||
net PB_RD_N loc=P2 | IOSTANDARD = LVCMOS33 ; # disk I/O read control
|
||||
net PB_WR_N loc=R1 | IOSTANDARD = LVCMOS33 ; # disk I/O write control
|
||||
net RESET_TRIGGER loc=D15 | IOSTANDARD = LVCMOS33 ; # Reset RESET_TRIGGER#
|
||||
#
|
||||
# IDE Interface
|
||||
#
|
||||
#net IDE_CS0_N loc=G15 | IOSTANDARD = LVCMOS33 ; # disk register-bank select
|
||||
#net IDE_CS1_N loc=G14 | IOSTANDARD = LVCMOS33 ; # disk register-bank select
|
||||
#net IDE_DMACK_N loc=K1 | IOSTANDARD = LVCMOS33 ; # (out) IDE DMA acknowledge
|
||||
#net IDE_DMARQ loc=L4 | IOSTANDARD = LVCMOS33 ; # (in) IDE DMA request
|
||||
#net IDE_IORDY loc=L2 | IOSTANDARD = LVCMOS33 ; # (in) IDE IO ready
|
||||
#net IDE_IRQ loc=H15 | IOSTANDARD = LVCMOS33 ; # (in) IDE interrupt # shared with BAR8
|
||||
#
|
||||
# Ethernet Controller
|
||||
# Disable if not used
|
||||
#
|
||||
net ether_cs_n loc=G13 | IOSTANDARD = LVCMOS33 ; # (out)Ethernet chip-enable
|
||||
net ether_aen loc=E14 | IOSTANDARD = LVCMOS33 ; # (out) Ethernet address enable not
|
||||
net ether_bhe_n loc=J3 | IOSTANDARD = LVCMOS33 ; # (out) Ethernet bus high enable
|
||||
net ether_clk loc=R9 | IOSTANDARD = LVCMOS33 ; # (in) Ethernet clock
|
||||
net ether_irq loc=L15 | IOSTANDARD = LVCMOS33 ; # (in) Ethernet irq - Shared with BAR6
|
||||
net ether_rdy loc=M2 | IOSTANDARD = LVCMOS33 ; # (in) Ethernet ready
|
||||
#
|
||||
# Expansion slots
|
||||
#
|
||||
#net slot1_cs_n loc=E15 | IOSTANDARD = LVCMOS33 ; # (out)
|
||||
#net slot1_irq loc=J16 | IOSTANDARD = LVCMOS33 ; # (in) Shared with BAR9
|
||||
#net slot2_cs_n loc=D16 | IOSTANDARD = LVCMOS33 ; # (out)
|
||||
#net slot2_irq loc=J14 | IOSTANDARD = LVCMOS33 ; # (in) Shared with BAR10
|
||||
#
|
||||
# Audio codec
|
||||
#
|
||||
#net audio_lrck loc=R12 | IOSTANDARD = LVCMOS33 ; # (out)
|
||||
#net audio_mclk loc=P11 | IOSTANDARD = LVCMOS33 ; # (out)
|
||||
#net audio_sclk loc=T12 | IOSTANDARD = LVCMOS33 ; # (out)
|
||||
#net audio_sdti loc=M10 | IOSTANDARD = LVCMOS33 ; # (out)
|
||||
#net audio_sdto loc=K5 | IOSTANDARD = LVCMOS33 ; # (in)
|
||||
#
|
||||
# i2c
|
||||
#
|
||||
#net i2c_scl loc=F5 | IOSTANDARD = LVCMOS33 ; #(out)
|
||||
#net i2c_sda loc=D2 | IOSTANDARD = LVCMOS33 ; # (in/out)
|
||||
#
|
||||
# USB
|
||||
#
|
||||
#NET USB_CLK LOC=M1 | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#NET USB_IRQ_N LOC=J13 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with BAR7
|
||||
#NET USB_SUSPEND LOC=l3 | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#
|
||||
# VIDEO DIGITIZER
|
||||
#
|
||||
#NET VIDIN_AVID LOC= | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#NET VIDIN_CLK LOC=H16 | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#NET VIDIN_FID LOC= | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#NET VIDIN_HSYNC LOC= | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#NET VIDIN_IRQ LOC= | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#NET VIDIN_VSYNC LOC= | IOSTANDARD = LVCMOS33 ; # (IN)
|
||||
#NET VIDIN_Y<0> LOC=H14 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_A
|
||||
#NET VIDIN_Y<1> LOC=M4 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_B
|
||||
#NET VIDIN_Y<2> LOC=P1 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_C
|
||||
#NET VIDIN_Y<3> LOC=N3 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_D
|
||||
#NET VIDIN_Y<4> LOC=M15 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_E
|
||||
#NET VIDIN_Y<5> LOC=H13 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_F
|
||||
#NET VIDIN_Y<6> LOC=G16 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_G
|
||||
#NET VIDIN_Y<7> LOC=N15 | IOSTANDARD = LVCMOS33 ; # (IN) Shared with LED1_DP
|
||||
#
|
||||
# Timing Constraints
|
||||
#
|
||||
NET "CLKA" TNM_NET="CLKA";
|
||||
TIMESPEC "TS_clk"=PERIOD "CLKA" 10 ns HIGH 50 %;
|
||||
174
j1/synth/xilinx.mk
Normal file
174
j1/synth/xilinx.mk
Normal file
@ -0,0 +1,174 @@
|
||||
# The top level module should define the variables below then include
|
||||
# this file. The files listed should be in the same directory as the
|
||||
# Makefile.
|
||||
#
|
||||
# variable description
|
||||
# ---------- -------------
|
||||
# project project name (top level module should match this name)
|
||||
# top_module top level module of the project
|
||||
# libdir path to library directory
|
||||
# libs library modules used
|
||||
# vfiles all local .v files
|
||||
# xilinx_cores all local .xco files
|
||||
# vendor vendor of FPGA (xilinx, altera, etc.)
|
||||
# family FPGA device family (spartan3e)
|
||||
# part FPGA part name (xc4vfx12-10-sf363)
|
||||
# flashsize size of flash for mcs file (16384)
|
||||
# optfile (optional) xst extra opttions file to put in .scr
|
||||
# map_opts (optional) options to give to map
|
||||
# par_opts (optional) options to give to par
|
||||
# intstyle (optional) intstyle option to all tools
|
||||
#
|
||||
# files description
|
||||
# ---------- ------------
|
||||
# $(project).ucf ucf file
|
||||
#
|
||||
# Library modules should have a modules.mk in their root directory,
|
||||
# namely $(libdir)/<libname>/module.mk, that simply adds to the vfiles
|
||||
# and xilinx_cores variable.
|
||||
#
|
||||
# all the .xco files listed in xilinx_cores will be generated with core, with
|
||||
# the resulting .v and .ngc files placed back in the same directory as
|
||||
# the .xco file.
|
||||
#
|
||||
# TODO: .xco files are device dependant, should use a template based system
|
||||
|
||||
coregen_work_dir ?= ./coregen-tmp
|
||||
map_opts ?= -timing -ol high -detail -pr b -register_duplication -w
|
||||
par_opts ?= -ol high
|
||||
isedir ?= /opt/Xilinx/11.1/ISE
|
||||
xil_env ?= . $(isedir)/settings32.sh
|
||||
flashsize ?= 8192
|
||||
|
||||
libmks = $(patsubst %,$(libdir)/%/module.mk,$(libs))
|
||||
mkfiles = Makefile $(libmks) xilinx.mk
|
||||
include $(libmks)
|
||||
|
||||
corengcs = $(foreach core,$(xilinx_cores),$(core:.xco=.ngc))
|
||||
local_corengcs = $(foreach ngc,$(corengcs),$(notdir $(ngc)))
|
||||
vfiles += $(foreach core,$(xilinx_cores),$(core:.xco=.v))
|
||||
junk += $(local_corengcs)
|
||||
|
||||
.PHONY: default xilinx_cores clean twr etwr
|
||||
default: $(project).bit $(project).mcs
|
||||
xilinx_cores: $(corengcs)
|
||||
twr: $(project).twr
|
||||
etwr: $(project)_err.twr
|
||||
|
||||
define cp_template
|
||||
$(2): $(1)
|
||||
cp $(1) $(2)
|
||||
endef
|
||||
$(foreach ngc,$(corengcs),$(eval $(call cp_template,$(ngc),$(notdir $(ngc)))))
|
||||
|
||||
%.ngc %.v: %.xco
|
||||
@echo "=== rebuilding $@"
|
||||
if [ -d $(coregen_work_dir) ]; then \
|
||||
rm -rf $(coregen_work_dir)/*; \
|
||||
else \
|
||||
mkdir -p $(coregen_work_dir); \
|
||||
fi
|
||||
cd $(coregen_work_dir); \
|
||||
$(xil_env); \
|
||||
coregen -b $$OLDPWD/$<; \
|
||||
cd -
|
||||
xcodir=`dirname $<`; \
|
||||
basename=`basename $< .xco`; \
|
||||
if [ ! -r $(coregen_work_dir/$$basename.ngc) ]; then \
|
||||
echo "'$@' wasn't created."; \
|
||||
exit 1; \
|
||||
else \
|
||||
cp $(coregen_work_dir)/$$basename.v $(coregen_work_dir)/$$basename.ngc $$xcodir; \
|
||||
fi
|
||||
junk += $(coregen_work_dir)
|
||||
|
||||
date = $(shell date +%F-%H-%M)
|
||||
|
||||
# some common junk
|
||||
junk += *.xrpt
|
||||
|
||||
programming_files: $(project).bit $(project).mcs
|
||||
mkdir -p $@/$(date)
|
||||
mkdir -p $@/latest
|
||||
for x in .bit .mcs .cfi _bd.bmm; do cp $(project)$$x $@/$(date)/$(project)$$x; cp $(project)$$x $@/latest/$(project)$$x; done
|
||||
$(xil_env); xst -help | head -1 | sed 's/^/#/' | cat - $(project).scr > $@/$(date)/$(project).scr
|
||||
|
||||
$(project).mcs: $(project).bit
|
||||
$(xil_env); \
|
||||
promgen -w -s $(flashsize) -p mcs -o $@ -u 0 $^
|
||||
junk += $(project).mcs $(project).cfi $(project).prm
|
||||
|
||||
$(project).bit: $(project)_par.ncd
|
||||
$(xil_env); \
|
||||
bitgen $(intstyle) -g DriveDone:yes -g StartupClk:Cclk -w $(project)_par.ncd $(project).bit
|
||||
junk += $(project).bgn $(project).bit $(project).drc $(project)_bd.bmm
|
||||
|
||||
|
||||
$(project)_par.ncd: $(project).ncd
|
||||
$(xil_env); \
|
||||
if par $(intstyle) $(par_opts) -w $(project).ncd $(project)_par.ncd; then \
|
||||
:; \
|
||||
else \
|
||||
$(MAKE) etwr; \
|
||||
fi
|
||||
junk += $(project)_par.ncd $(project)_par.par $(project)_par.pad
|
||||
junk += $(project)_par_pad.csv $(project)_par_pad.txt
|
||||
junk += $(project)_par.grf $(project)_par.ptwx
|
||||
junk += $(project)_par.unroutes $(project)_par.xpi
|
||||
|
||||
$(project).ncd: $(project).ngd
|
||||
if [ -r $(project)_par.ncd ]; then \
|
||||
cp $(project)_par.ncd smartguide.ncd; \
|
||||
smartguide="-smartguide smartguide.ncd"; \
|
||||
else \
|
||||
smartguide=""; \
|
||||
fi; \
|
||||
$(xil_env); \
|
||||
map $(intstyle) $(map_opts) $$smartguide $<
|
||||
junk += $(project).ncd $(project).pcf $(project).ngm $(project).mrp $(project).map
|
||||
junk += smartguide.ncd $(project).psr
|
||||
junk += $(project)_summary.xml $(project)_usage.xml
|
||||
|
||||
$(project).ngd: $(project).ngc $(project).ucf $(project).bmm
|
||||
$(xil_env); ngdbuild $(intstyle) $(project).ngc -bm $(project).bmm
|
||||
junk += $(project).ngd $(project).bld
|
||||
|
||||
$(project).ngc: $(vfiles) $(local_corengcs) $(project).scr $(project).prj
|
||||
$(xil_env); xst $(intstyle) -ifn $(project).scr
|
||||
junk += xlnx_auto* $(top_module).lso $(project).srp
|
||||
junk += netlist.lst xst $(project).ngc
|
||||
|
||||
$(project).prj: $(vfiles) $(mkfiles)
|
||||
for src in $(vfiles); do echo "verilog work $$src" >> $(project).tmpprj; done
|
||||
sort -u $(project).tmpprj > $(project).prj
|
||||
rm -f $(project).tmpprj
|
||||
junk += $(project).prj
|
||||
|
||||
optfile += $(wildcard $(project).opt)
|
||||
top_module ?= $(project)
|
||||
$(project).scr: $(optfile) $(mkfiles) ./xilinx.opt
|
||||
echo "run" > $@
|
||||
echo "-p $(part)" >> $@
|
||||
echo "-top $(top_module)" >> $@
|
||||
echo "-ifn $(project).prj" >> $@
|
||||
echo "-ofn $(project).ngc" >> $@
|
||||
cat ./xilinx.opt $(optfile) >> $@
|
||||
junk += $(project).scr
|
||||
|
||||
$(project).post_map.twr: $(project).ncd
|
||||
$(xil_env); trce -e 10 $< $(project).pcf -o $@
|
||||
junk += $(project).post_map.twr $(project).post_map.twx smartpreview.twr
|
||||
|
||||
$(project).twr: $(project)_par.ncd
|
||||
$(xil_env); trce $< $(project).pcf -o $(project).twr
|
||||
junk += $(project).twr $(project).twx smartpreview.twr
|
||||
|
||||
$(project)_err.twr: $(project)_par.ncd
|
||||
$(xil_env); trce -e 10 $< $(project).pcf -o $(project)_err.twr
|
||||
junk += $(project)_err.twr $(project)_err.twx
|
||||
|
||||
.gitignore: $(mkfiles)
|
||||
echo programming_files $(junk) | sed 's, ,\n,g' > .gitignore
|
||||
|
||||
clean::
|
||||
rm -rf $(junk)
|
||||
42
j1/synth/xilinx.opt
Normal file
42
j1/synth/xilinx.opt
Normal file
@ -0,0 +1,42 @@
|
||||
-ifmt mixed
|
||||
-ofmt NGC
|
||||
-opt_mode speed
|
||||
-opt_level 1
|
||||
-iuc NO
|
||||
-keep_hierarchy no
|
||||
-netlist_hierarchy as_optimized
|
||||
-rtlview no
|
||||
-glob_opt AllClockNets
|
||||
-read_cores yes
|
||||
-write_timing_constraints NO
|
||||
-cross_clock_analysis NO
|
||||
-hierarchy_separator /
|
||||
-bus_delimiter <>
|
||||
-case maintain
|
||||
-slice_utilization_ratio 100
|
||||
-bram_utilization_ratio 100
|
||||
#-dsp_utilization_ratio 100
|
||||
-safe_implementation No
|
||||
-fsm_extract YES
|
||||
-fsm_encoding Auto
|
||||
-fsm_style lut
|
||||
-ram_extract Yes
|
||||
-ram_style Auto
|
||||
-rom_extract Yes
|
||||
-rom_style Auto
|
||||
-shreg_extract YES
|
||||
-auto_bram_packing NO
|
||||
-resource_sharing YES
|
||||
-async_to_sync NO
|
||||
#-use_dsp48 auto
|
||||
-iobuf YES
|
||||
-max_fanout 500
|
||||
-register_duplication YES
|
||||
-register_balancing No
|
||||
-optimize_primitives NO
|
||||
-use_clock_enable Auto
|
||||
-use_sync_set Auto
|
||||
-use_sync_reset Auto
|
||||
-iob auto
|
||||
-equivalent_register_removal YES
|
||||
-slice_utilization_ratio_maxmargin 5
|
||||
41
j1/verilog/ck_div.v
Normal file
41
j1/verilog/ck_div.v
Normal file
@ -0,0 +1,41 @@
|
||||
module ck_div(
|
||||
input ck_in,
|
||||
output ck_out,
|
||||
input sys_rst_i
|
||||
//output locked;
|
||||
);
|
||||
parameter DIV_BY = 1;
|
||||
parameter MULT_BY = 1;
|
||||
|
||||
wire ck_fb;
|
||||
|
||||
//DCM #(
|
||||
// .CLKDV_DIVIDE(DIV_BY),
|
||||
// .DFS_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for frequency synthesis
|
||||
// .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
|
||||
// .STARTUP_WAIT("TRUE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE
|
||||
//) DCM_inst (
|
||||
// .CLK0(ck_fb),
|
||||
// .CLKDV(ck_out),
|
||||
// .CLKFB(ck_fb), // DCM clock feedback
|
||||
// .CLKIN(ck_in), // Clock input (from IBUFG, BUFG or DCM)
|
||||
// .RST(0)
|
||||
//);
|
||||
|
||||
DCM #(
|
||||
.CLKFX_MULTIPLY(MULT_BY),
|
||||
.CLKFX_DIVIDE(DIV_BY),
|
||||
.DFS_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for frequency synthesis
|
||||
.DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
|
||||
.STARTUP_WAIT("TRUE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE
|
||||
) DCM_inst (
|
||||
.CLK0(ck_fb),
|
||||
.CLKFX(ck_out),
|
||||
.CLKFB(ck_fb), // DCM clock feedback
|
||||
.CLKIN(ck_in), // Clock input (from IBUFG, BUFG or DCM)
|
||||
.RST(0)
|
||||
);
|
||||
|
||||
//BUFG BUFG_inst(.I(ck_int), .O(ck_out));
|
||||
|
||||
endmodule
|
||||
187
j1/verilog/j1.v
Normal file
187
j1/verilog/j1.v
Normal file
@ -0,0 +1,187 @@
|
||||
module j1(
|
||||
input sys_clk_i, input sys_rst_i, input [15:0] io_din,
|
||||
output io_rd, output io_wr, output [15:0] io_addr, output [15:0] io_dout);
|
||||
|
||||
wire [15:0] insn;
|
||||
wire [15:0] immediate = { 1'b0, insn[14:0] };
|
||||
|
||||
wire [15:0] ramrd;
|
||||
|
||||
reg [4:0] dsp; // Data stack pointer
|
||||
reg [4:0] _dsp;
|
||||
reg [15:0] st0; // Return stack pointer
|
||||
reg [15:0] _st0;
|
||||
wire _dstkW; // D stack write
|
||||
|
||||
reg [12:0] pc;
|
||||
reg [12:0] _pc;
|
||||
reg [4:0] rsp;
|
||||
reg [4:0] _rsp;
|
||||
reg _rstkW; // R stack write
|
||||
reg [15:0] _rstkD;
|
||||
wire _ramWE; // RAM write enable
|
||||
|
||||
wire [15:0] pc_plus_1;
|
||||
assign pc_plus_1 = pc + 1;
|
||||
|
||||
// The D and R stacks
|
||||
reg [15:0] dstack[0:31];
|
||||
reg [15:0] rstack[0:31];
|
||||
always @(posedge sys_clk_i)
|
||||
begin
|
||||
if (_dstkW)
|
||||
dstack[_dsp] = st0;
|
||||
if (_rstkW)
|
||||
rstack[_rsp] = _rstkD;
|
||||
end
|
||||
wire [15:0] st1 = dstack[dsp];
|
||||
wire [15:0] rst0 = rstack[rsp];
|
||||
|
||||
// st0sel is the ALU operation. For branch and call the operation
|
||||
// is T, for 0branch it is N. For ALU ops it is loaded from the instruction
|
||||
// field.
|
||||
reg [3:0] st0sel;
|
||||
always @*
|
||||
begin
|
||||
case (insn[14:13])
|
||||
2'b00: st0sel = 0; // ubranch
|
||||
2'b10: st0sel = 0; // call
|
||||
2'b01: st0sel = 1; // 0branch
|
||||
2'b11: st0sel = insn[11:8]; // ALU
|
||||
default: st0sel = 4'bxxxx;
|
||||
endcase
|
||||
end
|
||||
|
||||
`define RAMS 3
|
||||
|
||||
genvar i;
|
||||
|
||||
`define w (16 >> `RAMS)
|
||||
`define w1 (`w - 1)
|
||||
|
||||
generate
|
||||
for (i = 0; i < (1 << `RAMS); i=i+1) begin : ram
|
||||
// RAMB16_S18_S18
|
||||
RAMB16_S2_S2
|
||||
ram(
|
||||
.DIA(0),
|
||||
// .DIPA(0),
|
||||
.DOA(insn[`w*i+`w1:`w*i]),
|
||||
.WEA(0),
|
||||
.ENA(1),
|
||||
.CLKA(sys_clk_i),
|
||||
.ADDRA({_pc}),
|
||||
|
||||
.DIB(st1[`w*i+`w1:`w*i]),
|
||||
// .DIPB(2'b0),
|
||||
.WEB(_ramWE & (_st0[15:14] == 0)),
|
||||
.ENB(|_st0[15:14] == 0),
|
||||
.CLKB(sys_clk_i),
|
||||
.ADDRB(_st0[15:1]),
|
||||
.DOB(ramrd[`w*i+`w1:`w*i]));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Compute the new value of T.
|
||||
always @*
|
||||
begin
|
||||
if (insn[15])
|
||||
_st0 = immediate;
|
||||
else
|
||||
case (st0sel)
|
||||
4'b0000: _st0 = st0;
|
||||
4'b0001: _st0 = st1;
|
||||
4'b0010: _st0 = st0 + st1;
|
||||
4'b0011: _st0 = st0 & st1;
|
||||
4'b0100: _st0 = st0 | st1;
|
||||
4'b0101: _st0 = st0 ^ st1;
|
||||
4'b0110: _st0 = ~st0;
|
||||
4'b0111: _st0 = {16{(st1 == st0)}};
|
||||
4'b1000: _st0 = {16{($signed(st1) < $signed(st0))}};
|
||||
4'b1001: _st0 = st1 >> st0[3:0];
|
||||
4'b1010: _st0 = st0 - 1;
|
||||
4'b1011: _st0 = rst0;
|
||||
4'b1100: _st0 = |st0[15:14] ? io_din : ramrd;
|
||||
4'b1101: _st0 = st1 << st0[3:0];
|
||||
4'b1110: _st0 = {rsp, 3'b000, dsp};
|
||||
4'b1111: _st0 = {16{(st1 < st0)}};
|
||||
default: _st0 = 16'hxxxx;
|
||||
endcase
|
||||
end
|
||||
|
||||
wire is_alu = (insn[15:13] == 3'b011);
|
||||
wire is_lit = (insn[15]);
|
||||
|
||||
assign io_rd = (is_alu & (insn[11:8] == 4'hc));
|
||||
assign io_wr = _ramWE;
|
||||
assign io_addr = st0;
|
||||
assign io_dout = st1;
|
||||
|
||||
assign _ramWE = is_alu & insn[5];
|
||||
assign _dstkW = is_lit | (is_alu & insn[7]);
|
||||
|
||||
wire [1:0] dd = insn[1:0]; // D stack delta
|
||||
wire [1:0] rd = insn[3:2]; // R stack delta
|
||||
|
||||
always @*
|
||||
begin
|
||||
if (is_lit) begin // literal
|
||||
_dsp = dsp + 1;
|
||||
_rsp = rsp;
|
||||
_rstkW = 0;
|
||||
_rstkD = _pc;
|
||||
end else if (is_alu) begin
|
||||
_dsp = dsp + {dd[1], dd[1], dd[1], dd};
|
||||
_rsp = rsp + {rd[1], rd[1], rd[1], rd};
|
||||
_rstkW = insn[6];
|
||||
_rstkD = st0;
|
||||
end else begin // jump/call
|
||||
// predicated jump is like DROP
|
||||
if (insn[15:13] == 3'b001) begin
|
||||
_dsp = dsp - 1;
|
||||
end else begin
|
||||
_dsp = dsp;
|
||||
end
|
||||
if (insn[15:13] == 3'b010) begin // call
|
||||
_rsp = rsp + 1;
|
||||
_rstkW = 1;
|
||||
_rstkD = {pc_plus_1[14:0], 1'b0};
|
||||
end else begin
|
||||
_rsp = rsp;
|
||||
_rstkW = 0;
|
||||
_rstkD = _pc;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @*
|
||||
begin
|
||||
if (sys_rst_i)
|
||||
_pc = pc;
|
||||
else
|
||||
if ((insn[15:13] == 3'b000) |
|
||||
((insn[15:13] == 3'b001) & (|st0 == 0)) |
|
||||
(insn[15:13] == 3'b010))
|
||||
_pc = insn[12:0];
|
||||
else if (is_alu & insn[12])
|
||||
_pc = rst0[15:1];
|
||||
else
|
||||
_pc = pc_plus_1;
|
||||
end
|
||||
|
||||
always @(posedge sys_clk_i)
|
||||
begin
|
||||
if (sys_rst_i) begin
|
||||
pc <= 0;
|
||||
dsp <= 0;
|
||||
st0 <= 0;
|
||||
rsp <= 0;
|
||||
end else begin
|
||||
dsp <= _dsp;
|
||||
pc <= _pc;
|
||||
st0 <= _st0;
|
||||
rsp <= _rsp;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // j1
|
||||
36
j1/verilog/rams.v
Normal file
36
j1/verilog/rams.v
Normal file
@ -0,0 +1,36 @@
|
||||
module ram8_8(
|
||||
input [7:0] dia,
|
||||
output [7:0] doa,
|
||||
input wea,
|
||||
input ena,
|
||||
input clka,
|
||||
input [10:0] addra,
|
||||
|
||||
input [7:0] dib,
|
||||
output [7:0] dob,
|
||||
input web,
|
||||
input enb,
|
||||
input clkb,
|
||||
input [10:0] addrb
|
||||
);
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 4; i=i+1) begin : ramx
|
||||
RAMB16_S2_S2 ramx(
|
||||
.DIA(dia[2 * i + 1: 2 * i]),
|
||||
.WEA(wea),
|
||||
.ENA(ena),
|
||||
.CLKA(clka),
|
||||
.ADDRA(addra),
|
||||
.DOA(doa[2 * i + 1: 2 * i]),
|
||||
|
||||
.DIB(dib[2 * i + 1: 2 * i]),
|
||||
.WEB(web),
|
||||
.ENB(enb),
|
||||
.CLKB(clkb),
|
||||
.ADDRB(addrb),
|
||||
.DOB(dob[2 * i + 1: 2 * i])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
667
j1/verilog/top.v
Normal file
667
j1/verilog/top.v
Normal file
@ -0,0 +1,667 @@
|
||||
module bidir_io(
|
||||
input dir,
|
||||
input d,
|
||||
inout port);
|
||||
assign port = (dir) ? 1'bz : d;
|
||||
endmodule
|
||||
|
||||
module saturating_adder(
|
||||
input [7:0] a,
|
||||
input [7:0] b,
|
||||
input [7:0] c,
|
||||
input [7:0] d,
|
||||
input [7:0] e,
|
||||
input [7:0] f,
|
||||
input [7:0] g,
|
||||
input [7:0] h,
|
||||
input [7:0] i,
|
||||
output [7:0] sum);
|
||||
|
||||
wire [10:0] fullsum = a + b + c + d + e + f + g + h + i;
|
||||
assign sum = |fullsum[10:8] ? 255 : fullsum[7:0];
|
||||
endmodule
|
||||
|
||||
module partial(
|
||||
input [7:0] original,
|
||||
input alpha,
|
||||
input [2:0] scale, // by quarters
|
||||
output [7:0] result
|
||||
);
|
||||
assign result = alpha ? ((scale[0] ? original[7:2] : 0) +
|
||||
(scale[1] ? original[7:1] : 0) +
|
||||
(scale[2] ? original : 0)) : 0;
|
||||
endmodule
|
||||
|
||||
module lfsre(
|
||||
input clk,
|
||||
output reg [16:0] lfsr);
|
||||
wire d0;
|
||||
|
||||
xnor(d0,lfsr[16],lfsr[13]);
|
||||
|
||||
always @(posedge clk) begin
|
||||
lfsr <= {lfsr[15:0],d0};
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sprite(
|
||||
pixel_clk,
|
||||
picsel,
|
||||
pixel_x,
|
||||
pixel_y,
|
||||
sx, sy,
|
||||
write_data, write_address, write_en, write_clk,
|
||||
brightness,
|
||||
alpha
|
||||
);
|
||||
input pixel_clk;
|
||||
input picsel;
|
||||
input [9:0] pixel_x;
|
||||
input [9:0] pixel_y;
|
||||
input [9:0] sx;
|
||||
input [9:0] sy;
|
||||
input [8:0] write_data;
|
||||
input [11:0] write_address;
|
||||
input write_en;
|
||||
input write_clk;
|
||||
|
||||
output alpha;
|
||||
output [7:0] brightness;
|
||||
|
||||
wire [9:0] local_x = pixel_x - sx;
|
||||
wire [9:0] local_y = pixel_y - sy;
|
||||
wire [7:0] sprite_pixel;
|
||||
RAMB16_S9_S9 spriteram(
|
||||
.DIA(0),
|
||||
// .DIPA(0),
|
||||
.DOA(sprite_pixel),
|
||||
.WEA(0),
|
||||
.ENA(1),
|
||||
.CLKA(pixel_clk),
|
||||
.ADDRA({picsel, local_y[4:0], local_x[4:0]}),
|
||||
|
||||
.ADDRB(write_address),
|
||||
.DIPB(write_data[8]),
|
||||
.DIB(write_data),
|
||||
.WEB(write_en),
|
||||
.ENB(1),
|
||||
.CLKB(write_clk),
|
||||
.DOB());
|
||||
wire sprite_outside = |(local_y[9:5]) | |(local_x[9:5]);
|
||||
wire alpha = ~sprite_outside;
|
||||
wire [7:0] brightness = sprite_pixel; // sprite_outside ? 0 : sprite_pixel;
|
||||
endmodule
|
||||
|
||||
module top(
|
||||
// Outputs
|
||||
// s, // Onboard LED
|
||||
RS232_TXD, // RS232 transmit
|
||||
RESET_TRIGGER, // RESET-TRIGGER#
|
||||
|
||||
// Inputs
|
||||
clka,
|
||||
|
||||
pb_a, pb_d, pb_rd_n, pb_wr_n,
|
||||
|
||||
ether_cs_n, ether_aen, ether_bhe_n, ether_clk, ether_irq, ether_rdy,
|
||||
|
||||
// Flash
|
||||
flash_a, flash_d,
|
||||
flash_ce_n, flash_oe_n, flash_we_n, flash_byte_n, flash_rdy, flash_rst_n,
|
||||
|
||||
// PS/2 Keyboard
|
||||
ps2_clk, ps2_dat,
|
||||
|
||||
// Pushbuttons
|
||||
sw2_n, sw3_n,
|
||||
|
||||
// VGA
|
||||
vga_red, vga_green, vga_blue, vga_hsync_n, vga_vsync_n,
|
||||
|
||||
);
|
||||
|
||||
// output [7:0] s;
|
||||
output RS232_TXD;
|
||||
output RESET_TRIGGER;
|
||||
inout [4:0] pb_a;
|
||||
output ether_cs_n;
|
||||
output ether_aen;
|
||||
output ether_bhe_n;
|
||||
output pb_rd_n;
|
||||
output pb_wr_n;
|
||||
|
||||
input clka;
|
||||
input ether_clk;
|
||||
input ether_irq;
|
||||
input ether_rdy;
|
||||
|
||||
inout [15:0] pb_d;
|
||||
|
||||
output [19:0] flash_a;
|
||||
|
||||
inout [15:0] flash_d;
|
||||
|
||||
output flash_ce_n;
|
||||
output flash_oe_n;
|
||||
output flash_we_n;
|
||||
output flash_byte_n;
|
||||
output flash_rdy;
|
||||
output flash_rst_n;
|
||||
|
||||
reg ps2_clk_dir;
|
||||
reg ps2_dat_dir;
|
||||
reg ps2_clk_d;
|
||||
reg ps2_dat_d;
|
||||
inout ps2_clk;
|
||||
inout ps2_dat;
|
||||
bidir_io ps2_clkb(.dir(ps2_clk_dir), .d(ps2_clk_d), .port(ps2_clk));
|
||||
bidir_io ps2_datb(.dir(ps2_dat_dir), .d(ps2_dat_d), .port(ps2_dat));
|
||||
|
||||
input sw2_n;
|
||||
input sw3_n;
|
||||
|
||||
output [2:0] vga_red;
|
||||
output [2:0] vga_green;
|
||||
output [2:0] vga_blue;
|
||||
output vga_hsync_n;
|
||||
output vga_vsync_n;
|
||||
|
||||
wire j1_io_rd;
|
||||
wire j1_io_wr;
|
||||
wire [15:0] j1_io_addr;
|
||||
reg [15:0] j1_io_din;
|
||||
wire [15:0] j1_io_dout;
|
||||
|
||||
wire sys_clk;
|
||||
ck_div #(.DIV_BY(12), .MULT_BY(4)) sys_ck_gen(.ck_in(clka), .ck_out(sys_clk));
|
||||
|
||||
// ================================================
|
||||
// Hardware multiplier
|
||||
|
||||
reg [15:0] mult_a;
|
||||
reg [15:0] mult_b;
|
||||
wire [31:0] mult_p;
|
||||
MULT18X18 mulinsn(.A(mult_a), .B(mult_b), .P(mult_p));
|
||||
// MULT18X18SIO #(
|
||||
// .AREG(0),
|
||||
// .BREG(0),
|
||||
// .PREG(0))
|
||||
// MULT18X18SIO(
|
||||
// .A(mult_a),
|
||||
// .B(mult_b),
|
||||
// .P(mult_p));
|
||||
|
||||
// ================================================
|
||||
// 32-bit 1-MHz system clock
|
||||
|
||||
reg [5:0] clockus;
|
||||
wire [5:0] _clockus = (clockus == 32) ? 0 : (clockus + 1);
|
||||
reg [31:0] clock;
|
||||
wire [31:0] _clock = (clockus == 32) ? (clock + 1) : (clock);
|
||||
|
||||
always @(posedge sys_clk)
|
||||
begin
|
||||
clockus <= _clockus;
|
||||
clock <= _clock;
|
||||
end
|
||||
|
||||
// reg [7:0] s;
|
||||
reg RS232_TXD;
|
||||
reg RESET_TRIGGER;
|
||||
|
||||
reg ether_cs_n;
|
||||
reg ether_aen;
|
||||
reg ether_bhe_n;
|
||||
reg ddir;
|
||||
|
||||
reg [15:0] pb_dout;
|
||||
assign pb_d = (ddir) ? 16'bz : pb_dout;
|
||||
reg pb_rd_n;
|
||||
reg pb_wr_n;
|
||||
|
||||
reg pb_a_dir;
|
||||
reg [4:0] pb_aout;
|
||||
assign pb_a = pb_a_dir ? 5'bz : pb_aout;
|
||||
|
||||
reg flash_ddir;
|
||||
reg [19:0] flash_a;
|
||||
reg [15:0] flash_dout;
|
||||
assign flash_d[14:0] = (flash_ddir) ? 15'bz : flash_dout[14:0];
|
||||
assign flash_d[15] = (flash_ddir & flash_byte_n) ? 1'bz : flash_dout[15];
|
||||
reg flash_ce_n;
|
||||
reg flash_oe_n;
|
||||
reg flash_we_n;
|
||||
reg flash_byte_n;
|
||||
reg flash_rdy;
|
||||
reg flash_rst_n;
|
||||
|
||||
reg [12:0] vga_scroll;
|
||||
reg [13:0] vga_spritea;
|
||||
reg [9:0] vga_spritex[7:0];
|
||||
reg [9:0] vga_spritey[7:0];
|
||||
reg vga_addsprites;
|
||||
reg [10:0] vga_spritec0;
|
||||
reg [10:0] vga_spritec1;
|
||||
reg [10:0] vga_spritec2;
|
||||
reg [10:0] vga_spritec3;
|
||||
reg [10:0] vga_spritec4;
|
||||
reg [10:0] vga_spritec5;
|
||||
reg [10:0] vga_spritec6;
|
||||
reg [10:0] vga_spritec7;
|
||||
wire [9:0] vga_line;
|
||||
reg [7:0] vga_spritesel;
|
||||
|
||||
always @(posedge sys_clk)
|
||||
begin
|
||||
if (j1_io_wr) begin
|
||||
case (j1_io_addr)
|
||||
// 16'h4000: s <= j1_io_dout;
|
||||
|
||||
16'h4100: flash_ddir <= j1_io_dout;
|
||||
16'h4102: flash_ce_n <= j1_io_dout;
|
||||
16'h4104: flash_oe_n <= j1_io_dout;
|
||||
16'h4106: flash_we_n <= j1_io_dout;
|
||||
16'h4108: flash_byte_n <= j1_io_dout;
|
||||
16'h410a: flash_rdy <= j1_io_dout;
|
||||
16'h410c: flash_rst_n <= j1_io_dout;
|
||||
16'h410e: flash_a[15:0] <= j1_io_dout;
|
||||
16'h4110: flash_a[19:16] <= j1_io_dout;
|
||||
16'h4112: flash_dout <= j1_io_dout;
|
||||
|
||||
16'h4200: ps2_clk_d <= j1_io_dout;
|
||||
16'h4202: ps2_dat_d <= j1_io_dout;
|
||||
16'h4204: ps2_clk_dir <= j1_io_dout;
|
||||
16'h4206: ps2_dat_dir <= j1_io_dout;
|
||||
|
||||
16'h4300: vga_scroll <= j1_io_dout;
|
||||
16'h4302: vga_spritea <= j1_io_dout;
|
||||
// 16'h4304: vga_spriteport
|
||||
16'h4308: vga_addsprites <= j1_io_dout;
|
||||
|
||||
16'h4400: vga_spritex[0] <= j1_io_dout;
|
||||
16'h4402: vga_spritey[0] <= j1_io_dout;
|
||||
16'h4404: vga_spritex[1] <= j1_io_dout;
|
||||
16'h4406: vga_spritey[1] <= j1_io_dout;
|
||||
16'h4408: vga_spritex[2] <= j1_io_dout;
|
||||
16'h440a: vga_spritey[2] <= j1_io_dout;
|
||||
16'h440c: vga_spritex[3] <= j1_io_dout;
|
||||
16'h440e: vga_spritey[3] <= j1_io_dout;
|
||||
16'h4410: vga_spritex[4] <= j1_io_dout;
|
||||
16'h4412: vga_spritey[4] <= j1_io_dout;
|
||||
16'h4414: vga_spritex[5] <= j1_io_dout;
|
||||
16'h4416: vga_spritey[5] <= j1_io_dout;
|
||||
16'h4418: vga_spritex[6] <= j1_io_dout;
|
||||
16'h441a: vga_spritey[6] <= j1_io_dout;
|
||||
16'h441c: vga_spritex[7] <= j1_io_dout;
|
||||
16'h441e: vga_spritey[7] <= j1_io_dout;
|
||||
|
||||
16'h4420: vga_spritec0 <= j1_io_dout;
|
||||
16'h4422: vga_spritec1 <= j1_io_dout;
|
||||
16'h4424: vga_spritec2 <= j1_io_dout;
|
||||
16'h4426: vga_spritec3 <= j1_io_dout;
|
||||
16'h4428: vga_spritec4 <= j1_io_dout;
|
||||
16'h442a: vga_spritec5 <= j1_io_dout;
|
||||
16'h442c: vga_spritec6 <= j1_io_dout;
|
||||
16'h442e: vga_spritec7 <= j1_io_dout;
|
||||
|
||||
16'h4430: vga_spritesel[0] <= j1_io_dout;
|
||||
16'h4432: vga_spritesel[1] <= j1_io_dout;
|
||||
16'h4434: vga_spritesel[2] <= j1_io_dout;
|
||||
16'h4436: vga_spritesel[3] <= j1_io_dout;
|
||||
16'h4438: vga_spritesel[4] <= j1_io_dout;
|
||||
16'h443a: vga_spritesel[5] <= j1_io_dout;
|
||||
16'h443c: vga_spritesel[6] <= j1_io_dout;
|
||||
16'h443e: vga_spritesel[7] <= j1_io_dout;
|
||||
|
||||
16'h5000: RS232_TXD <= j1_io_dout;
|
||||
16'h5001: RESET_TRIGGER <= j1_io_dout;
|
||||
16'h5100: ether_cs_n <= j1_io_dout;
|
||||
16'h5101: ether_aen <= j1_io_dout;
|
||||
16'h5102: ether_bhe_n <= j1_io_dout;
|
||||
16'h5103: pb_aout <= j1_io_dout;
|
||||
16'h5104: ddir <= j1_io_dout;
|
||||
16'h5105: pb_dout <= j1_io_dout;
|
||||
16'h5106: pb_rd_n <= j1_io_dout;
|
||||
16'h5107: pb_wr_n <= j1_io_dout;
|
||||
// 5108
|
||||
// 5109
|
||||
16'h510a: pb_a_dir <= j1_io_dout;
|
||||
|
||||
16'h6100: mult_a <= j1_io_dout;
|
||||
16'h6102: mult_b <= j1_io_dout;
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always @*
|
||||
begin
|
||||
case (j1_io_addr)
|
||||
16'h4112: j1_io_din = flash_d;
|
||||
|
||||
16'h4200: j1_io_din = ps2_clk;
|
||||
16'h4202: j1_io_din = ps2_dat;
|
||||
|
||||
16'h4300: j1_io_din = vga_scroll;
|
||||
16'h4306: j1_io_din = vga_line;
|
||||
|
||||
16'h4500: j1_io_din = sw2_n;
|
||||
16'h4502: j1_io_din = sw3_n;
|
||||
|
||||
16'h5103: j1_io_din = pb_a;
|
||||
16'h5105: j1_io_din = pb_d;
|
||||
16'h5108: j1_io_din = ether_rdy;
|
||||
16'h5109: j1_io_din = ether_irq;
|
||||
|
||||
16'h6000: j1_io_din = clock[15:0];
|
||||
16'h6002: j1_io_din = clock[31:16];
|
||||
|
||||
16'h6104: j1_io_din = mult_p[15:0];
|
||||
16'h6106: j1_io_din = mult_p[31:16];
|
||||
|
||||
default: j1_io_din = 16'h0946;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [10:0] reset_count = 1000;
|
||||
wire sys_rst_i = |reset_count;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if (sys_rst_i)
|
||||
reset_count <= reset_count - 1;
|
||||
end
|
||||
|
||||
j1 j1(
|
||||
// Inputs
|
||||
.sys_clk_i (sys_clk),
|
||||
.sys_rst_i (sys_rst_i),
|
||||
|
||||
.io_rd(j1_io_rd),
|
||||
.io_wr(j1_io_wr),
|
||||
.io_addr(j1_io_addr),
|
||||
.io_din(j1_io_din),
|
||||
.io_dout(j1_io_dout)
|
||||
);
|
||||
|
||||
/*
|
||||
uart uart(
|
||||
// Outputs
|
||||
.uart_busy (uart_busy),
|
||||
.uart_tx (RS232_TXD),
|
||||
// Inputs
|
||||
.uart_wr_i (j1_uart_we),
|
||||
.uart_dat_i (j1_io_dout),
|
||||
.sys_clk_i (sys_clk_i),
|
||||
.sys_rst_i (sys_rst_i));
|
||||
*/
|
||||
|
||||
// ================================================
|
||||
// VGA
|
||||
|
||||
wire vga_clk;
|
||||
ck_div #(.DIV_BY(4), .MULT_BY(2)) vga_ck_gen(.ck_in(clka), .ck_out(vga_clk));
|
||||
|
||||
reg [10:0] CounterX;
|
||||
reg [9:0] CounterY;
|
||||
wire CounterXmaxed = (CounterX==1040);
|
||||
|
||||
always @(posedge vga_clk)
|
||||
if(CounterXmaxed)
|
||||
CounterX <= 0;
|
||||
else
|
||||
CounterX <= CounterX + 1;
|
||||
|
||||
wire [9:0] _CounterY = (CounterY == 666) ? 0 : (CounterY + 1);
|
||||
always @(posedge vga_clk)
|
||||
if(CounterXmaxed)
|
||||
CounterY <= _CounterY;
|
||||
|
||||
reg vga_HS, vga_VS;
|
||||
always @(posedge vga_clk)
|
||||
begin
|
||||
vga_HS <= (53 <= CounterX) & (CounterX < (53 + 120));
|
||||
vga_VS <= (35 <= CounterY) & (CounterY < (35 + 6));
|
||||
end
|
||||
|
||||
// Character RAM is 2K
|
||||
wire [10:0] xx = (CounterX - (53 + 120 + 61));
|
||||
wire [10:0] xx_1 = (CounterX - (53 + 120 + 61) + 1);
|
||||
// standard timing, except (600-512)/2=44 at top and bottom
|
||||
wire [10:0] yy = (CounterY - (35 + 6 + 21 + 44));
|
||||
wire [10:0] column = xx[10:1];
|
||||
wire [10:0] column_1 = xx_1[10:1];
|
||||
wire [10:0] row = yy[10:1];
|
||||
wire [7:0] glyph;
|
||||
|
||||
wire [10:0] picaddr = {(row[7:3] + vga_scroll[4:0]), column_1[8:3]};
|
||||
|
||||
// genvar i;
|
||||
// generate
|
||||
// for (i = 0; i < 4; i=i+1) begin : picture
|
||||
// RAMB16_S2_S2 picture(
|
||||
// .DIA(0),
|
||||
// // .DIPA(0),
|
||||
// .DOA(glyph[2 * i + 1: 2 * i]),
|
||||
// .WEA(0),
|
||||
// .ENA(1),
|
||||
// .CLKA(vga_clk),
|
||||
// .ADDRA(spicaddr),
|
||||
//
|
||||
// // .DIPB(0),
|
||||
// .DIB(j1_io_dout[2 * i + 1: 2 * i]),
|
||||
// .WEB(j1_io_wr & (j1_io_addr[15:13] == 3'b100)),
|
||||
// .ENB(1),
|
||||
// .CLKB(sys_clk),
|
||||
// .ADDRB(j1_io_addr),
|
||||
// .DOB());
|
||||
// end
|
||||
// endgenerate
|
||||
|
||||
// RAMB16_S9_S9 picture(
|
||||
// .DIA(0),
|
||||
// // .DIPA(0),
|
||||
// .DOA(glyph),
|
||||
// .WEA(0),
|
||||
// .ENA(1),
|
||||
// .CLKA(vga_clk),
|
||||
// .ADDRA(picaddr),
|
||||
//
|
||||
// .DIPB(0),
|
||||
// .DIB(j1_io_dout),
|
||||
// .WEB(j1_io_wr & (j1_io_addr[15:13] == 3'b100)),
|
||||
// .ENB(1),
|
||||
// .CLKB(sys_clk),
|
||||
// .ADDRB(j1_io_addr),
|
||||
// .DOB());
|
||||
wire pic_w = j1_io_wr & (j1_io_addr[15:13] == 3'b100);
|
||||
ram8_8 picture(
|
||||
.dia(0), .doa(glyph), .wea(0), .ena(1), .clka(vga_clk), .addra(picaddr),
|
||||
.dib(j1_io_dout), .web(pic_w), .enb(1), .clkb(sys_clk), .addrb(j1_io_addr));
|
||||
|
||||
wire charout;
|
||||
RAMB16_S1_S9 chars(
|
||||
.DIA(0),
|
||||
// .DIPA(0),
|
||||
.DOA(charout),
|
||||
.WEA(0),
|
||||
.ENA(1),
|
||||
.CLKA(vga_clk),
|
||||
.ADDRA({glyph, row[2:0], ~column[2:0]}),
|
||||
|
||||
.DIPB(0),
|
||||
.DIB(j1_io_dout),
|
||||
// .DIPB(2'b0),
|
||||
.WEB(j1_io_wr & (j1_io_addr[15:12] == 4'hf)),
|
||||
.ENB(1),
|
||||
.CLKB(sys_clk),
|
||||
.ADDRB(j1_io_addr),
|
||||
.DOB());
|
||||
|
||||
reg [10:0] regxx;
|
||||
always @(posedge vga_clk)
|
||||
begin
|
||||
regxx <= xx;
|
||||
end
|
||||
|
||||
wire [63:0] sprite_pixels;
|
||||
wire [7:0] alpha;
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 8; i=i+1) begin : sprite_n
|
||||
sprite sprite_n(
|
||||
.pixel_clk(vga_clk),
|
||||
.picsel(vga_spritesel[i]),
|
||||
.pixel_x(regxx),
|
||||
.pixel_y(yy),
|
||||
.sx(vga_spritex[i]),
|
||||
.sy(vga_spritey[i]),
|
||||
.write_data(j1_io_dout),
|
||||
.write_address(vga_spritea),
|
||||
.write_en(j1_io_wr & (j1_io_addr == 16'h4304) & (vga_spritea[13:11] == i)),
|
||||
.write_clk(sys_clk),
|
||||
.alpha(alpha[i]),
|
||||
.brightness(sprite_pixels[8*i+7:8*i]));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// wire [10:0] brightsum = bright[0] + bright[1] + bright[2] + bright[3] + bright[4] + bright[5] + bright[6] + bright[7];
|
||||
// wire [7:0] brightness = |brightsum[10:8] ? 255 : brightsum[7:0];
|
||||
// wire [7:0] final_bright = |alpha ? 255 : 0;
|
||||
|
||||
// wire [7:0] final_bright = sprite_pixels[39:32];
|
||||
|
||||
wire [7:0] sprite0 = sprite_pixels[7:0];
|
||||
wire [7:0] sprite1 = sprite_pixels[15:8];
|
||||
wire [7:0] sprite2 = sprite_pixels[23:16];
|
||||
wire [7:0] sprite3 = sprite_pixels[31:24];
|
||||
wire [7:0] sprite4 = sprite_pixels[39:32];
|
||||
wire [7:0] sprite5 = sprite_pixels[47:40];
|
||||
wire [7:0] sprite6 = sprite_pixels[55:48];
|
||||
wire [7:0] sprite7 = sprite_pixels[63:56];
|
||||
|
||||
reg [10:0] fullsum;
|
||||
reg [7:0] final_bright;
|
||||
|
||||
wire [16:0] lfsr;
|
||||
lfsre lfsr0(
|
||||
.clk(vga_clk),
|
||||
.lfsr(lfsr));
|
||||
wire [7:0] charout8 = {8{charout}};
|
||||
wire [7:0] dither = {lfsr[0], lfsr[4], lfsr[8], lfsr[12], lfsr[16]} | charout8;
|
||||
|
||||
wire [7:0] r0;
|
||||
wire [7:0] r1;
|
||||
wire [7:0] r2;
|
||||
wire [7:0] r3;
|
||||
wire [7:0] r4;
|
||||
wire [7:0] r5;
|
||||
wire [7:0] r6;
|
||||
wire [7:0] r7;
|
||||
wire [7:0] g0;
|
||||
wire [7:0] g1;
|
||||
wire [7:0] g2;
|
||||
wire [7:0] g3;
|
||||
wire [7:0] g4;
|
||||
wire [7:0] g5;
|
||||
wire [7:0] g6;
|
||||
wire [7:0] g7;
|
||||
wire [7:0] b0;
|
||||
wire [7:0] b1;
|
||||
wire [7:0] b2;
|
||||
wire [7:0] b3;
|
||||
wire [7:0] b4;
|
||||
wire [7:0] b5;
|
||||
wire [7:0] b6;
|
||||
wire [7:0] b7;
|
||||
|
||||
wire [2:0] spr0r = vga_spritec0[10:8];
|
||||
wire [2:0] spr1r = vga_spritec1[10:8];
|
||||
wire [2:0] spr2r = vga_spritec2[10:8];
|
||||
wire [2:0] spr3r = vga_spritec3[10:8];
|
||||
wire [2:0] spr4r = vga_spritec4[10:8];
|
||||
wire [2:0] spr5r = vga_spritec5[10:8];
|
||||
wire [2:0] spr6r = vga_spritec6[10:8];
|
||||
wire [2:0] spr7r = vga_spritec7[10:8];
|
||||
wire [2:0] spr0g = vga_spritec0[6:4];
|
||||
wire [2:0] spr1g = vga_spritec1[6:4];
|
||||
wire [2:0] spr2g = vga_spritec2[6:4];
|
||||
wire [2:0] spr3g = vga_spritec3[6:4];
|
||||
wire [2:0] spr4g = vga_spritec4[6:4];
|
||||
wire [2:0] spr5g = vga_spritec5[6:4];
|
||||
wire [2:0] spr6g = vga_spritec6[6:4];
|
||||
wire [2:0] spr7g = vga_spritec7[6:4];
|
||||
wire [2:0] spr0b = vga_spritec0[2:0];
|
||||
wire [2:0] spr1b = vga_spritec1[2:0];
|
||||
wire [2:0] spr2b = vga_spritec2[2:0];
|
||||
wire [2:0] spr3b = vga_spritec3[2:0];
|
||||
wire [2:0] spr4b = vga_spritec4[2:0];
|
||||
wire [2:0] spr5b = vga_spritec5[2:0];
|
||||
wire [2:0] spr6b = vga_spritec6[2:0];
|
||||
wire [2:0] spr7b = vga_spritec7[2:0];
|
||||
|
||||
partial pr0(sprite0, alpha[0], spr0r, r0);
|
||||
partial pr1(sprite1, alpha[1], spr1r, r1);
|
||||
partial pr2(sprite2, alpha[2], spr2r, r2);
|
||||
partial pr3(sprite3, alpha[3], spr3r, r3);
|
||||
partial pr4(sprite4, alpha[4], spr4r, r4);
|
||||
partial pr5(sprite5, alpha[5], spr5r, r5);
|
||||
partial pr6(sprite6, alpha[6], spr6r, r6);
|
||||
partial pr7(sprite7, alpha[7], spr7r, r7);
|
||||
|
||||
partial pg0(sprite0, alpha[0], spr0g, g0);
|
||||
partial pg1(sprite1, alpha[1], spr1g, g1);
|
||||
partial pg2(sprite2, alpha[2], spr2g, g2);
|
||||
partial pg3(sprite3, alpha[3], spr3g, g3);
|
||||
partial pg4(sprite4, alpha[4], spr4g, g4);
|
||||
partial pg5(sprite5, alpha[5], spr5g, g5);
|
||||
partial pg6(sprite6, alpha[6], spr6g, g6);
|
||||
partial pg7(sprite7, alpha[7], spr7g, g7);
|
||||
|
||||
partial pb0(sprite0, alpha[0], spr0b, b0);
|
||||
partial pb1(sprite1, alpha[1], spr1b, b1);
|
||||
partial pb2(sprite2, alpha[2], spr2b, b2);
|
||||
partial pb3(sprite3, alpha[3], spr3b, b3);
|
||||
partial pb4(sprite4, alpha[4], spr4b, b4);
|
||||
partial pb5(sprite5, alpha[5], spr5b, b5);
|
||||
partial pb6(sprite6, alpha[6], spr6b, b6);
|
||||
partial pb7(sprite7, alpha[7], spr7b, b7);
|
||||
|
||||
wire [7:0] sat_r;
|
||||
saturating_adder add_r(r0, r1, r2, r3, r4, r5, r6, r7, dither, sat_r);
|
||||
wire [7:0] sat_g;
|
||||
saturating_adder add_g(g0, g1, g2, g3, g4, g5, g6, g7, dither, sat_g);
|
||||
wire [7:0] sat_b;
|
||||
saturating_adder add_b(b0, b1, b2, b3, b4, b5, b6, b7, dither, sat_b);
|
||||
|
||||
always @*
|
||||
begin
|
||||
if(vga_addsprites) begin
|
||||
final_bright = sat_r;
|
||||
end else begin
|
||||
if(alpha[0]) final_bright = sprite0;
|
||||
else if(alpha[1]) final_bright = sprite1;
|
||||
else if(alpha[2]) final_bright = sprite2;
|
||||
else if(alpha[3]) final_bright = sprite3;
|
||||
else if(alpha[4]) final_bright = sprite4;
|
||||
else if(alpha[5]) final_bright = sprite5;
|
||||
else if(alpha[6]) final_bright = sprite6;
|
||||
else if(alpha[7]) final_bright = sprite7;
|
||||
else
|
||||
final_bright = 0;
|
||||
end
|
||||
end
|
||||
|
||||
wire active = ((53 + 120 + 61) <= CounterX) & (CounterX < (53 + 120 + 61 + 800)) & ((35 + 6 + 21 + 44) < CounterY) & (CounterY < (35 + 6 + 21 + 44 + 512));
|
||||
assign vga_line = yy;
|
||||
// wire [2:0] vga_red = active ? (charout ? 7 : 0) : 0;
|
||||
// wire [2:0] vga_red = active ? final_bright[7:5] : 0;
|
||||
// wire [2:0] vga_green = active ? final_bright[7:5] : 0;
|
||||
// wire [2:0] vga_blue = active ? final_bright[7:5] : 0;
|
||||
wire [2:0] vga_red = active ? sat_r[7:5] : 0;
|
||||
wire [2:0] vga_green = active ? sat_g[7:5] : 0;
|
||||
wire [2:0] vga_blue = active ? sat_b[7:5] : 0;
|
||||
wire vga_hsync_n = ~vga_HS;
|
||||
wire vga_vsync_n = ~vga_VS;
|
||||
|
||||
endmodule // top
|
||||
|
||||
BIN
python/471fcf9e.png
Normal file
BIN
python/471fcf9e.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
8
python/duplicator.py
Normal file
8
python/duplicator.py
Normal file
@ -0,0 +1,8 @@
|
||||
class Duplicator(object):
|
||||
def __init__(self, objs):
|
||||
self.objs = objs
|
||||
def __getattr__(self, name):
|
||||
def bcast(*args):
|
||||
return [o.__getattribute__(name)(*args) for o in self.objs]
|
||||
return bcast
|
||||
|
||||
1
python/gameduino/__init__.py
Normal file
1
python/gameduino/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from gameduino.registers import *
|
||||
207
python/gameduino/base.py
Normal file
207
python/gameduino/base.py
Normal file
@ -0,0 +1,207 @@
|
||||
import struct
|
||||
|
||||
ascii_glyphs = [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00,
|
||||
0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x7f, 0x36, 0x7f, 0x36, 0x36, 0x00,
|
||||
0x0c, 0x3f, 0x68, 0x3e, 0x0b, 0x7e, 0x18, 0x00, 0x60, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x06, 0x00,
|
||||
0x38, 0x6c, 0x6c, 0x38, 0x6d, 0x66, 0x3b, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00,
|
||||
0x00, 0x18, 0x7e, 0x3c, 0x7e, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00,
|
||||
0x3c, 0x66, 0x6e, 0x7e, 0x76, 0x66, 0x3c, 0x00, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00,
|
||||
0x3c, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00,
|
||||
0x0c, 0x1c, 0x3c, 0x6c, 0x7e, 0x0c, 0x0c, 0x00, 0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00,
|
||||
0x1c, 0x30, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
|
||||
0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0x38, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30,
|
||||
0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00,
|
||||
0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x3c, 0x66, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x00,
|
||||
|
||||
0x3c, 0x66, 0x6e, 0x6a, 0x6e, 0x60, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00,
|
||||
0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00,
|
||||
0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, 0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x7e, 0x00,
|
||||
0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00,
|
||||
0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00,
|
||||
0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x6b, 0x63, 0x63, 0x00,
|
||||
0x66, 0x66, 0x76, 0x7e, 0x6e, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
||||
0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6a, 0x6c, 0x36, 0x00,
|
||||
0x7c, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00,
|
||||
0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x63, 0x63, 0x6b, 0x6b, 0x7f, 0x77, 0x63, 0x00,
|
||||
0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00,
|
||||
0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x00,
|
||||
0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3e, 0x00,
|
||||
0x18, 0x3c, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
|
||||
0x1c, 0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
|
||||
0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00,
|
||||
0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
|
||||
0x1c, 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x3c,
|
||||
0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||
0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x00,
|
||||
0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x36, 0x7f, 0x6b, 0x6b, 0x63, 0x00,
|
||||
0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00,
|
||||
0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x07,
|
||||
0x00, 0x00, 0x6c, 0x76, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00,
|
||||
0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00,
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x6b, 0x7f, 0x36, 0x00,
|
||||
0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c,
|
||||
0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x0c, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0c, 0x00,
|
||||
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x30, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x30, 0x00,
|
||||
0x31, 0x6b, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
]
|
||||
|
||||
from gameduino.registers import *
|
||||
|
||||
# BaseGameduino is the common base for the Gameduino objects in remote and sim
|
||||
|
||||
class BaseGameduino(object):
|
||||
|
||||
def coldstart(self):
|
||||
self.wr(J1_RESET, 1)
|
||||
self.fill(RAM_PIC, 0, 10 * 1024)
|
||||
for i in range(512):
|
||||
self.sprite(i, 400, 400, 0, 0, 0)
|
||||
self.wr16(SPR_DISABLE, 0)
|
||||
self.wr16(SPR_PAGE, 0)
|
||||
self.wr16(JK_MODE, 0)
|
||||
self.wr16(SCROLL_X, 0)
|
||||
self.wr16(SCROLL_Y, 0)
|
||||
self.wr16(BG_COLOR, 0)
|
||||
self.wr16(SAMPLE_L, 0)
|
||||
self.wr16(SAMPLE_R, 0)
|
||||
self.wr16(SCREENSHOT_Y, 0)
|
||||
|
||||
def dump(self, a, l):
|
||||
""" Dump ``l`` bytes memory starting at address ``a`` """
|
||||
for i in range(0, l, 16):
|
||||
d16 = self.rdstr(a + i, 16)
|
||||
print "%04x %s" % (a + i, " ".join(["%02x" % ord(c) for c in d16]))
|
||||
|
||||
def wr(self, a, v):
|
||||
""" Write a single byte ``v`` to address ``a``. """
|
||||
self.wrstr(a, chr(v))
|
||||
|
||||
def fill(self, a, v, c):
|
||||
""" Fill ``c`` bytes of memory at address ``a`` with value ``v`` """
|
||||
self.wrstr(a, chr(v) * c)
|
||||
|
||||
def putstr(self, x, y, v):
|
||||
""" Write string ``v`` at screen position (x,y) """
|
||||
a = y * 64 + x
|
||||
self.wrstr(a, v)
|
||||
|
||||
def rd16(self, a):
|
||||
return struct.unpack("<H", self.rdstr(a, 2))[0]
|
||||
|
||||
def rd32(self, a):
|
||||
return struct.unpack("<L", self.rdstr(a, 4))[0]
|
||||
|
||||
def wr16(self, a, v):
|
||||
""" Write 16-bit value ``v`` at to address ``a`` """
|
||||
self.wrstr(a, struct.pack("<H", v))
|
||||
|
||||
def wr32(self, a, v):
|
||||
""" Write 32-bit value ``v`` at to address ``a`` """
|
||||
self.wrstr(a, struct.pack("<L", v))
|
||||
|
||||
def setpal(self, pal, rgb):
|
||||
self.wr16(RAM_PAL + (pal << 1), rgb);
|
||||
|
||||
def ascii(self):
|
||||
stretch = [
|
||||
0x00, 0x03, 0x0c, 0x0f,
|
||||
0x30, 0x33, 0x3c, 0x3f,
|
||||
0xc0, 0xc3, 0xcc, 0xcf,
|
||||
0xf0, 0xf3, 0xfc, 0xff ]
|
||||
gstr = ""
|
||||
for i in range(768):
|
||||
b = ascii_glyphs[i]
|
||||
h = stretch[b >> 4]
|
||||
l = stretch[b & 0xf]
|
||||
gstr += chr(h)
|
||||
gstr += chr(l)
|
||||
self.wrstr(0x1000 + (16 * ord(' ')), gstr)
|
||||
for i in range(0x20, 0x80):
|
||||
self.setpal(4 * i + 0, TRANSPARENT);
|
||||
self.setpal(4 * i + 3, RGB(255,255,255));
|
||||
self.fill(RAM_PIC, ord(' '), 4096);
|
||||
|
||||
def voice(self, v, wave, freq, lamp, ramp = None):
|
||||
"""
|
||||
Set the state of a voice.
|
||||
|
||||
:param v: voice number 0-63
|
||||
:type v: int
|
||||
:param wave: wave type, 0 for sine 1 for noise
|
||||
:type wave: int
|
||||
:param freq: frequency control, in quarter-hertz
|
||||
:type freq: int
|
||||
:param lamp: left amplitude 0-255
|
||||
:type lamp: int
|
||||
:param ramp: right amplitude 0-255, defaults to same ``lamp``
|
||||
:type ramp: int
|
||||
"""
|
||||
if ramp is None:
|
||||
ramp = lamp
|
||||
self.wr32(VOICES + (4 * v), freq | (wave << 15) | (lamp << 16) | (ramp << 24))
|
||||
|
||||
def silence(self):
|
||||
""" Switch all voices off """
|
||||
for i in range(64):
|
||||
self.voice(i, 0, 4 * 440, 0, 0)
|
||||
|
||||
def copy(self, a, v):
|
||||
self.wrstr(a, v)
|
||||
|
||||
def microcode(self, src):
|
||||
"""
|
||||
Halt coprocessor, load microprogram, restart coprocessor
|
||||
|
||||
:param src: the microprogram, as a string, expressed
|
||||
:type src: string
|
||||
|
||||
The string is loaded into the Gameduino's microprogram area,
|
||||
and can be up to 256 bytes. For example, to load the
|
||||
:ref:`splitscreen` microprogram::
|
||||
|
||||
splitscreen_code = open("splitscreen.binle", "b").read()
|
||||
gd.microcode(splitscreen_code)
|
||||
|
||||
"""
|
||||
|
||||
self.wr(J1_RESET, 1)
|
||||
self.copy(J1_CODE, src)
|
||||
self.wr(J1_RESET, 0)
|
||||
|
||||
def sprite(self, spr, x, y, image, palette, rot, jk = 0):
|
||||
"""
|
||||
Set the state of a hardware sprite
|
||||
|
||||
:param spr: sprite number 0-511
|
||||
:param x: x coordinate
|
||||
:param y: y coordinate
|
||||
:param image: sprite source image 0-63
|
||||
:param palette: sprite palette select, 0-15, see below
|
||||
:param rot: sprite rotate control 0-7, see :ref:`rotate`
|
||||
:param jk: collision class control, 0-1
|
||||
|
||||
Palette select controls the number of colors used for the sprite, the source palette, and which data bits
|
||||
to use as source.
|
||||
|
||||
"""
|
||||
|
||||
self.wr32(RAM_SPR + (4 * spr),
|
||||
(x & 511) | ((rot & 7) << 9) | ((palette & 15) << 12) | ((y & 511) << 16) | ((image & 63) << 25) | ((jk & 1) << 31))
|
||||
|
||||
def im(self):
|
||||
"""
|
||||
Return the current screen as a 400x300 RGB PIL Image::
|
||||
|
||||
>>> import gameduino.sim
|
||||
>>> gd = gameduino.sim.Gameduino()
|
||||
>>> gd.im().save("screenshot.png")
|
||||
"""
|
||||
return self._im()
|
||||
174
python/gameduino/compress.py
Normal file
174
python/gameduino/compress.py
Normal file
@ -0,0 +1,174 @@
|
||||
import time
|
||||
import sys
|
||||
import array
|
||||
|
||||
def prefix(s1, s2):
|
||||
""" Return the length of the common prefix of s1 and s2 """
|
||||
sz = len(s2)
|
||||
for i in range(sz):
|
||||
if s1[i % len(s1)] != s2[i]:
|
||||
return i
|
||||
return sz
|
||||
|
||||
def runlength(blk, p0, p1):
|
||||
""" p0 is the source position, p1 is the dest position
|
||||
Return the length of run of common chars
|
||||
"""
|
||||
for i in range(1, len(blk) - p1):
|
||||
if blk[p0:p0+i] != blk[p1:p1+i]:
|
||||
return i - 1
|
||||
return len(blk) - p1 - 1
|
||||
|
||||
def runlength2(blk, p0, p1, bsf):
|
||||
""" p0 is the source position, p1 is the dest position
|
||||
Return the length of run of common chars
|
||||
"""
|
||||
if blk[p0:p0+bsf+1] != blk[p1:p1+bsf+1]:
|
||||
return 0
|
||||
for i in range(bsf + 1, len(blk) - p1):
|
||||
if blk[p0:p0+i] != blk[p1:p1+i]:
|
||||
return i - 1
|
||||
return len(blk) - p1 - 1
|
||||
|
||||
class Bitstream(object):
|
||||
def __init__(self):
|
||||
self.b = []
|
||||
def append(self, sz, v):
|
||||
assert 0 <= v
|
||||
assert v < (1 << sz)
|
||||
for i in range(sz):
|
||||
self.b.append(1 & (v >> (sz - 1 - i)))
|
||||
def toarray(self):
|
||||
bb = [0] * ((len(self.b) + 7) / 8)
|
||||
for i,b in enumerate(self.b):
|
||||
if b:
|
||||
bb[i / 8] |= (1 << (i & 7));
|
||||
return array.array('B', bb)
|
||||
|
||||
class Codec(object):
|
||||
def __init__(self, b_off, b_len):
|
||||
self.b_off = b_off
|
||||
self.b_len = b_len
|
||||
self.history = 2 ** b_off
|
||||
refsize = (1 + self.b_off + self.b_len) # bits needed for a backreference
|
||||
if refsize < 9:
|
||||
self.M = 1
|
||||
elif refsize < 18:
|
||||
self.M = 2
|
||||
else:
|
||||
self.M = 3
|
||||
# print "M", self.M
|
||||
# e.g. M 2, b_len 4, so: 0->2, 15->17
|
||||
self.maxlen = self.M + (2**self.b_len) - 1
|
||||
|
||||
def compress(self, blk):
|
||||
lempel = {}
|
||||
sched = []
|
||||
pos = 0
|
||||
while pos < len(blk):
|
||||
k = blk[pos:pos+self.M]
|
||||
older = (pos - self.history - 1)
|
||||
candidates = set([p for p in lempel.get(k, []) if (older < p)])
|
||||
lempel[k] = candidates # prune old
|
||||
# print pos, repr(k), len(lempel), "lempels", "candidates", len(candidates)
|
||||
def addlempel(c):
|
||||
if c in lempel:
|
||||
lempel[c].add(pos)
|
||||
else:
|
||||
lempel[c] = set([pos])
|
||||
if 0:
|
||||
# (bestlen, bestpos) = max([(0, 0)] + [(prefix(blk[p:pos], blk[pos:]), p) for p in candidates])
|
||||
(bestlen, bestpos) = max([(0, 0)] + [(runlength(blk, p, pos), p) for p in candidates])
|
||||
bestlen = min(bestlen, self.maxlen)
|
||||
else:
|
||||
(bestlen, bestpos) = (0, None)
|
||||
for p in candidates:
|
||||
cl = runlength2(blk, p, pos, bestlen)
|
||||
if cl > bestlen:
|
||||
bestlen,bestpos = cl,p
|
||||
if self.maxlen <= bestlen:
|
||||
bestlen = min(bestlen, self.maxlen)
|
||||
break
|
||||
if bestlen >= self.M:
|
||||
sched.append((bestpos - pos, bestlen))
|
||||
for i in range(bestlen):
|
||||
addlempel(blk[pos:pos+self.M])
|
||||
pos += 1
|
||||
else:
|
||||
addlempel(k)
|
||||
sched.append(blk[pos])
|
||||
pos += 1
|
||||
return sched
|
||||
|
||||
def toarray(self, blk):
|
||||
sched = self.compress(blk)
|
||||
return self.sched2bs(sched)
|
||||
|
||||
def sched2bs(self, sched):
|
||||
bs = Bitstream()
|
||||
bs.append(4, self.b_off)
|
||||
bs.append(4, self.b_len)
|
||||
bs.append(2, self.M)
|
||||
bs.append(16, len(sched))
|
||||
for c in sched:
|
||||
if len(c) != 1:
|
||||
(offset, l) = c
|
||||
bs.append(1, 1)
|
||||
bs.append(self.b_off, -offset - 1)
|
||||
bs.append(self.b_len, l - self.M)
|
||||
else:
|
||||
bs.append(1, 0)
|
||||
bs.append(8, ord(c))
|
||||
return bs.toarray()
|
||||
|
||||
def to_cfile(self, hh, blk, name):
|
||||
print >>hh, "static PROGMEM prog_uchar %s[] = {" % name
|
||||
bb = self.toarray(blk)
|
||||
for i in range(0, len(bb), 16):
|
||||
if (i & 0xff) == 0:
|
||||
print >>hh
|
||||
for c in bb[i:i+16]:
|
||||
print >>hh, "0x%02x, " % c,
|
||||
print >>hh
|
||||
print >>hh, "};"
|
||||
|
||||
def decompress(self, sched):
|
||||
s = ""
|
||||
for c in sched:
|
||||
if len(c) == 1:
|
||||
s += c
|
||||
else:
|
||||
(offset, l) = c
|
||||
for i in range(l):
|
||||
s += s[offset]
|
||||
return s
|
||||
|
||||
def main():
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser("%prog [ --lookback O ] [ --length L ] --name NAME inputfile outputfile")
|
||||
|
||||
parser.add_option("--lookback", type=int, default=8, dest="O", help="lookback field size in bits")
|
||||
parser.add_option("--length", type=int, default=3, dest="L", help="length field size in bits")
|
||||
parser.add_option("--name", type=str, default="data", dest="NAME", help="name for generated C array")
|
||||
parser.add_option("--binary", action="store_true", default=False, dest="binary", help="write a binary file (default is to write a C++ header file)")
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if len(args) != 2:
|
||||
parser.error("must specify input and output files");
|
||||
|
||||
print options.O
|
||||
print options.L
|
||||
print options.NAME
|
||||
print args
|
||||
(inputfile, outputfile) = args
|
||||
cc = Codec(b_off = options.O, b_len = options.L)
|
||||
uncompressed = open(inputfile, "rb").read()
|
||||
if options.binary:
|
||||
compressed = cc.toarray(uncompressed)
|
||||
open(outputfile, "wb").write(compressed.tostring())
|
||||
else:
|
||||
outfile = open(outputfile, "w")
|
||||
cc.to_cfile(outfile, uncompressed, options.NAME)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
498
python/gameduino/prep.py
Normal file
498
python/gameduino/prep.py
Normal file
@ -0,0 +1,498 @@
|
||||
"""
|
||||
gameduino.prep - for graphics and sound preparation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The prep module provides utilities for
|
||||
preparing Gameduino media: images and sound.
|
||||
These utilities can be used, for example, to take image files
|
||||
and encode them so that the Gameduino can display them as backgrounds
|
||||
or sprites.
|
||||
|
||||
|
||||
..
|
||||
This module defines mnemonics for the sprite palette select field:
|
||||
+-----------------------+-------+
|
||||
| PALETTE256A | 0 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE256B | 1 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE256C | 2 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE256D | 3 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE16A_BITS0123 | 4 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE16A_BITS4567 | 6 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE16B_BITS0123 | 5 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE16B_BITS4567 | 7 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4A_BITS01 | 8 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4A_BITS23 | 10 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4A_BITS45 | 12 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4A_BITS67 | 14 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4B_BITS01 | 9 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4B_BITS23 | 11 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4B_BITS45 | 13 |
|
||||
+-----------------------+-------+
|
||||
| PALETTE4B_BITS67 | 15 |
|
||||
+-----------------------+-------+
|
||||
|
||||
The module defines these constants for use as the ``palset`` argument to :meth:`ImageRAM.addsprites`:
|
||||
|
||||
+-------------+-------------------------+
|
||||
| PALETTE256A | 256-color palette A |
|
||||
+-------------+-------------------------+
|
||||
| PALETTE256B | 256-color palette B |
|
||||
+-------------+-------------------------+
|
||||
| PALETTE256C | 256-color palette C |
|
||||
+-------------+-------------------------+
|
||||
| PALETTE256D | 256-color palette D |
|
||||
+-------------+-------------------------+
|
||||
| PALETTE4A | Four-color palette A |
|
||||
+-------------+-------------------------+
|
||||
| PALETTE4B | Four-color palette B |
|
||||
+-------------+-------------------------+
|
||||
| PALETTE16A | Sixteen-color palette A |
|
||||
+-------------+-------------------------+
|
||||
| PALETTE16B | Sixteen-color palette B |
|
||||
+-------------+-------------------------+
|
||||
|
||||
"""
|
||||
|
||||
PALETTE256A = [0]
|
||||
PALETTE256B = [1]
|
||||
PALETTE256C = [2]
|
||||
PALETTE256D = [3]
|
||||
PALETTE4A_BITS01 = (0x8 + (0 << 1))
|
||||
PALETTE4A_BITS23 = (0x8 + (1 << 1))
|
||||
PALETTE4A_BITS45 = (0x8 + (2 << 1))
|
||||
PALETTE4A_BITS67 = (0x8 + (3 << 1))
|
||||
PALETTE4A = (PALETTE4A_BITS01, PALETTE4A_BITS23, PALETTE4A_BITS45, PALETTE4A_BITS67)
|
||||
PALETTE4B_BITS01 = (0x8 + (0 << 1) + 1)
|
||||
PALETTE4B_BITS23 = (0x8 + (1 << 1) + 1)
|
||||
PALETTE4B_BITS45 = (0x8 + (2 << 1) + 1)
|
||||
PALETTE4B_BITS67 = (0x8 + (3 << 1) + 1)
|
||||
PALETTE4B = (PALETTE4B_BITS01, PALETTE4B_BITS23, PALETTE4B_BITS45, PALETTE4B_BITS67)
|
||||
|
||||
PALETTE16A_BITS0123 = (0x4 + (0 << 1))
|
||||
PALETTE16A_BITS4567 = (0x4 + (1 << 1))
|
||||
PALETTE16A = (PALETTE16A_BITS0123, PALETTE16A_BITS4567)
|
||||
PALETTE16B_BITS0123 = (0x4 + (0 << 1) + 1)
|
||||
PALETTE16B_BITS4567 = (0x4 + (1 << 1) + 1)
|
||||
PALETTE16B = (PALETTE16B_BITS0123, PALETTE16B_BITS4567)
|
||||
|
||||
from array import array
|
||||
import Image
|
||||
|
||||
def dump(hh, name, data):
|
||||
"""
|
||||
Writes data to a header file for use in an Arduino Sketch.
|
||||
|
||||
:param hh: destination header file
|
||||
:type hh: :class:`file`
|
||||
:param name: the name of the object, as it will appear in the header file
|
||||
:type name: string
|
||||
:param data: the data to be dumped
|
||||
:type data: :class:`array.array`
|
||||
"""
|
||||
print >>hh, "static PROGMEM prog_uchar %s[] = {" % name
|
||||
bb = array('B', data.tostring())
|
||||
for i in range(0, len(bb), 16):
|
||||
if (i & 0xff) == 0:
|
||||
print >>hh
|
||||
for c in bb[i:i+16]:
|
||||
print >>hh, "0x%02x, " % c,
|
||||
print >>hh
|
||||
print >>hh, "};"
|
||||
|
||||
def rgbpal(imdata):
|
||||
# For RGBA imdata, return list of (r,g,b) triples and the palette
|
||||
li = array('B', imdata).tolist()
|
||||
rgbas = zip(li[0::4], li[1::4], li[2::4], li[3::4])
|
||||
palette = list(set(rgbas))
|
||||
return (rgbas, palette)
|
||||
|
||||
def getch(im, x, y):
|
||||
# return the RGBA data for the 8x8 character at (x, y) in im
|
||||
# if the 8x8 RGB contains more than 4 colors, quantize it using
|
||||
# `scolorq <http://www.cs.berkeley.edu/~dcoetzee/downloads/scolorq/>`_.
|
||||
|
||||
sub88 = im.crop((x, y, x + 8, y + 8))
|
||||
sub88d = sub88.tostring()
|
||||
|
||||
(_, pal) = rgbpal(sub88d)
|
||||
if len(pal) > 4:
|
||||
return sub88.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=4).convert("RGBA")
|
||||
else:
|
||||
return sub88
|
||||
|
||||
def rgb555(r, g, b):
|
||||
return ((r / 8) << 10) + ((g / 8) << 5) + (b / 8)
|
||||
|
||||
def rgba1555(r, g, b, a):
|
||||
return ((a < 128) << 15) + ((r / 8) << 10) + ((g / 8) << 5) + (b / 8)
|
||||
|
||||
def encodech(imdata):
|
||||
"""
|
||||
imdata is 8x8x4 RGBA character, string of length 256
|
||||
return the pixel and palette data for it as
|
||||
:class:`array.array` of type 'B' and 'H' respectively.
|
||||
"""
|
||||
|
||||
assert len(imdata) == (4 * 8 * 8)
|
||||
(rgbs, palette) = rgbpal(imdata)
|
||||
indices = [palette.index(c) for c in rgbs]
|
||||
indices_b = ""
|
||||
for i in range(0, len(indices), 4):
|
||||
c = ((indices[i] << 6) +
|
||||
(indices[i + 1] << 4) +
|
||||
(indices[i + 2] << 2) +
|
||||
(indices[i + 3]))
|
||||
indices_b += (chr(c))
|
||||
palette = (palette + ([(0,0,0,255)] * 4))[:4] # unused palette entries: opaque black
|
||||
ph = array('H', [rgba1555(*p) for p in palette])
|
||||
return (indices_b, ph)
|
||||
|
||||
def getpal(im):
|
||||
""" im is a paletted image. Return its palette as a Gameduino sprite palette
|
||||
in an :class:`array.array` of type 'H'. This form can be used directly with :func:`dump`::
|
||||
|
||||
import gameduino.prep as gdprep
|
||||
...
|
||||
gdprep.dump(hfile, "paletteA", gdprep.getpal(im))
|
||||
|
||||
"""
|
||||
|
||||
ncol = ord(max(im.tostring())) + 1
|
||||
ncol = min([c for c in [4,16,256] if c >= ncol])
|
||||
lut = im.resize((ncol, 1))
|
||||
lut.putdata(range(ncol))
|
||||
palstr = lut.convert("RGB").tostring()
|
||||
rgbs = zip(*(array('B', palstr[i::3]) for i in range(3)))
|
||||
rgb555 = [(((r / 8) << 10) | ((g / 8) << 5) | (b / 8)) for (r,g,b) in rgbs]
|
||||
if 'transparency' in im.info:
|
||||
rgb555[im.info['transparency']] = 0x8000
|
||||
return array('H', rgb555)
|
||||
|
||||
def encode(im):
|
||||
"""
|
||||
Convert a PIL image to a Gameduino character background image.
|
||||
|
||||
:param im: A Python Imaging Library image
|
||||
:rtype: tuple of data for (picture, character, font) all :class:`array.array`.
|
||||
|
||||
The image must have dimensions that are multiples of 8.
|
||||
If any character cell contains more than four colors, then the cell's pixel are quantized to four colors before encoding.
|
||||
If the image requires more than 256 unique character cells, this function throws exception OverflowError.
|
||||
The tuple returned contains three pieces of data:
|
||||
|
||||
* picture - the bytes representing the character cells. For input image sized (w, h) this array has size (w/8)*(h/8). Type of this array is 'B' (unsigned byte)
|
||||
* character - the glyphs for all used 8x8 characters. One character is 16 bytes. Type of this array is 'B' (unsigned byte)
|
||||
* palette - the 4-color palettes for all used 8x8 characters. One character is 8 bytes. Type of this array is 'H' (unsigned short)
|
||||
|
||||
To display the image, load these three arrays into Gameduino memory. For example,
|
||||
to encode a single image and
|
||||
write its data to a header file ``titlescreen.h``::
|
||||
|
||||
import gameduino.prep as gdprep
|
||||
(dpic, dchr, dpal) = gdprep.encode(Image.open("titlescreen.png"))
|
||||
hdr = open("titlescreen.h", "w")
|
||||
gdprep.dump(hdr, "titlescreen_pic", dpic)
|
||||
gdprep.dump(hdr, "titlescreen_chr", dchr)
|
||||
gdprep.dump(hdr, "titlescreen_pal", dpal)
|
||||
|
||||
and to display the image on the screen, an Arduino sketch might do::
|
||||
|
||||
#include "titlescreen.h"
|
||||
|
||||
void setup()
|
||||
{
|
||||
...
|
||||
GD.copy(RAM_PIC, titlescreen_pic, sizeof(titlescreen_pic));
|
||||
GD.copy(RAM_CHR, titlescreen_chr, sizeof(titlescreen_chr));
|
||||
GD.copy(RAM_PAL, titlescreen_pal, sizeof(titlescreen_pal));
|
||||
|
||||
"""
|
||||
|
||||
if im.mode != "RGBA":
|
||||
im = im.convert("RGBA")
|
||||
charset = {} # dict that maps 8x8 images to byte charcodes
|
||||
picture = [] # 64x64 byte picture RAM
|
||||
for y in range(0, im.size[1], 8):
|
||||
for x in range(0, im.size[0], 8):
|
||||
iglyph = getch(im, x, y)
|
||||
glyph = iglyph.tostring()
|
||||
if not glyph in charset:
|
||||
if len(charset) == 256:
|
||||
raise OverflowError
|
||||
charset[glyph] = len(charset)
|
||||
picture.append(charset[glyph])
|
||||
picd = array('B', picture)
|
||||
cd = array('B', [0] * 16 * len(charset))
|
||||
pd = array('H', [0] * 4 * len(charset))
|
||||
for d,i in charset.items():
|
||||
for y in range(8):
|
||||
(char, pal) = encodech(d)
|
||||
cd[16 * i:16 * (i+1)] = array('B', char)
|
||||
pd[4 * i:4 * (i+1)] = pal
|
||||
return (picd, cd, pd)
|
||||
|
||||
def preview(picd, cd, pd):
|
||||
preview = Image.new("RGB", im.size)
|
||||
preview.paste(iglyph, (x, y))
|
||||
return preview
|
||||
|
||||
def glom(sizes):
|
||||
""" Returns a master size and a list of crop/paste coordinates """
|
||||
mw = max(w for (w,h) in sizes)
|
||||
mh = sum(h for (w,h) in sizes)
|
||||
y = 0
|
||||
r = []
|
||||
for (w,h) in sizes:
|
||||
r.append((0, y, w, y + h))
|
||||
y += h
|
||||
return ((mw,mh), r)
|
||||
|
||||
|
||||
def palettize(im, ncol):
|
||||
""" Given an input image or list of images, convert to a palettized version using at most ``ncol`` colors.
|
||||
This function preserves transparency: if the input(s) have transparency then the returned
|
||||
image(s) have ``.info['transparency']`` set to the transparent color.
|
||||
|
||||
If ``im`` is a single image, returns a single image. If ``im`` is a list of images, returns a list of images.
|
||||
"""
|
||||
|
||||
assert ncol in (4, 16, 256)
|
||||
if isinstance(im, list):
|
||||
# For a list of images, paste them all into a single image,
|
||||
# palettize the single image, then return cropped subimages
|
||||
|
||||
for i in im:
|
||||
i.load()
|
||||
(ms, lpos) = glom([i.size for i in im])
|
||||
master = Image.new(im[0].mode, ms)
|
||||
for i,ps in zip(im, lpos):
|
||||
master.paste(i, ps)
|
||||
master = palettize(master, ncol)
|
||||
ims = [master.crop(ps) for ps in lpos]
|
||||
for i in ims:
|
||||
i.info = master.info
|
||||
return ims
|
||||
else:
|
||||
im.load()
|
||||
|
||||
if im.mode == 'P':
|
||||
if ord(max(im.tostring())) < ncol:
|
||||
return im # already done
|
||||
if 'transparency' in im.info:
|
||||
im = im.convert("RGBA")
|
||||
else:
|
||||
im = im.convert("RGB")
|
||||
assert im.mode in ("RGBA", "RGB")
|
||||
if im.mode == "RGB":
|
||||
return im.convert('P', palette=Image.ADAPTIVE, colors=ncol)
|
||||
else:
|
||||
alpha = im.split()[3]
|
||||
mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
|
||||
im.paste((0,0,0), mask)
|
||||
im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors = (ncol - 1))
|
||||
im.paste(ncol - 1, mask)
|
||||
im.info['transparency'] = ncol - 1
|
||||
return im
|
||||
|
||||
def isnonblank(im):
|
||||
assert im.mode == 'P'
|
||||
if 'transparency' in im.info:
|
||||
transparent = im.info['transparency']
|
||||
(w,h) = im.size
|
||||
colors = set([im.getpixel((i, j)) for i in range(w) for j in range(h)])
|
||||
return colors != set([transparent])
|
||||
else:
|
||||
return True
|
||||
|
||||
class ImageRAM(object):
|
||||
"""
|
||||
|
||||
The ImageRAM object simplifies loading of the Gameduino's 16K sprite image RAM.
|
||||
A caller adds sprite images to the ImageRAM, and finally obtains a memory image
|
||||
using :meth:`ImageRAM.used`.
|
||||
|
||||
"""
|
||||
def __init__(self, hh):
|
||||
self.hh = hh
|
||||
self.data = array('B', [0] * 16384)
|
||||
self.nxtpage = 0 # next available page
|
||||
self.nxtbit = 0 # next available bit
|
||||
|
||||
def __bump(self, b):
|
||||
self.nxtbit += b
|
||||
if 8 == self.nxtbit:
|
||||
self.nxtbit = 0
|
||||
self.nxtpage += 1
|
||||
|
||||
def add(self, page, size):
|
||||
"""
|
||||
Add a sprite image to the ImageRAM
|
||||
|
||||
:param page: image data, a list length 256
|
||||
:param size: size of data elements, either 4, 16 or 256
|
||||
:rtype: Returns a tuple (image, pal)
|
||||
|
||||
This method adds the data in ``page`` to the ImageRAM, and the returns the assigned location. ``image`` is the
|
||||
sprite image 0-63 containing the data, and ``pal`` is the palette bit select for the data.
|
||||
|
||||
For a 4-color image, ``pal`` is 0-3, for 16-color image ``pal`` is 0-1 and for a 256-color image ``pal`` is 0.
|
||||
|
||||
The ``image`` and ``pal`` values may be used to display the sprite using :cpp:func:`GD::sprite`.
|
||||
|
||||
If the data would cause the ImageRAM to increase beyond 16K, this method throws exception OverflowError.
|
||||
"""
|
||||
assert size in (4,16,256)
|
||||
assert max(page) < size, "%d colors allowed, but page contains %d" % (size, max(page))
|
||||
assert len(page) == 256
|
||||
|
||||
bits = {4:2, 16:4, 256:8}[size]
|
||||
while (self.nxtbit % bits) != 0:
|
||||
self.__bump(2)
|
||||
if self.nxtpage == 64:
|
||||
raise OverflowError
|
||||
if size == 4:
|
||||
pal = self.nxtbit / 2
|
||||
elif size == 16:
|
||||
pal = self.nxtbit / 4
|
||||
else:
|
||||
pal = 0
|
||||
pg = self.nxtpage
|
||||
for i in range(256):
|
||||
self.data[256 * self.nxtpage + i] |= (page[i] << self.nxtbit)
|
||||
self.__bump(bits)
|
||||
return (pg, pal)
|
||||
|
||||
def addsprites(self, name, size, im, palset = PALETTE256A, center = (0,0)):
|
||||
"""
|
||||
Extract multiple sprite frames from a source image, and generate the code to draw them.
|
||||
|
||||
:param name: name of the sprite set; used to name the generated ``draw_`` function
|
||||
:param size: size of each sprite frame (width, height)
|
||||
:param im: source image, mode must be 'P' - paletted
|
||||
:param palset: palette set to use for the sprite, one of PALETTE256A-D, PALETTE16A-B, PALETTE4A-B
|
||||
:param center: the center pixel of the sprite image. Default is (0,0) meaning top left pixel.
|
||||
|
||||
Given a sequence of sprite frames in ``im``, this method extracts their data and adds it to the ImageRAM.
|
||||
In addition, it writes the code to draw the sprite to the ImageRAM's header file. For example::
|
||||
|
||||
import gameduino.prep as gdprep
|
||||
ir = gdprep.ImageRAM(open("hdr.h", "w"))
|
||||
rock0 = gdprep.palettize(Image.open("rock0r.png"), 16)
|
||||
ir.addsprites("rock0", (16, 16), rock0, gdprep.PALETTE16A, center = (8,8))
|
||||
|
||||
would extract the four 16x16 frames from the ``rock0r.png`` image:
|
||||
|
||||
.. image:: rock0r.png
|
||||
|
||||
and write the following code to ``hdr.h``::
|
||||
|
||||
#define ROCK0_FRAMES 4
|
||||
static void draw_rock0(int x, int y, byte anim, byte rot, byte jk = 0) {
|
||||
...
|
||||
}
|
||||
|
||||
For more more examples, see the :ref:`asteroids` demo game.
|
||||
"""
|
||||
|
||||
def get16x16(sheet, x, y):
|
||||
return sheet.crop((16*x, 16*y, 16*(x+1), 16*(y+1)))
|
||||
|
||||
def walktile(im, size):
|
||||
for y in range(0, im.size[1], size[1]):
|
||||
for x in range(0, im.size[0], size[0]):
|
||||
yield im.crop((x, y, x + size[0], y + size[1]))
|
||||
tiles = list(walktile(im, size))
|
||||
|
||||
print >>self.hh, "#define %s_FRAMES %d" % (name.upper(), len(tiles))
|
||||
animtype = ["byte", "int"][len(tiles) > 255]
|
||||
print >>self.hh, """static void draw_%s(int x, int y, %s anim, byte rot, byte jk = 0) {\n switch (anim) {""" % (name, animtype)
|
||||
if palset == PALETTE256A:
|
||||
ncolors = 256
|
||||
elif palset == PALETTE256B:
|
||||
ncolors = 256
|
||||
elif palset == PALETTE256C:
|
||||
ncolors = 256
|
||||
elif palset == PALETTE256D:
|
||||
ncolors = 256
|
||||
elif palset == PALETTE4A:
|
||||
ncolors = 4
|
||||
elif palset == PALETTE4B:
|
||||
ncolors = 4
|
||||
elif palset == PALETTE16A:
|
||||
ncolors = 16
|
||||
elif palset == PALETTE16B:
|
||||
ncolors = 16
|
||||
else:
|
||||
highest = ord(max(im.tostring()))
|
||||
ncolors = min([c for c in [4,16,256] if (highest < c)])
|
||||
for spr,spriteimage in enumerate(tiles):
|
||||
loads = []
|
||||
for y in range((size[1] + 15) / 16):
|
||||
for x in range((size[0] + 15) / 16):
|
||||
t = get16x16(spriteimage, x, y)
|
||||
t.info = im.info # workaround: PIL does not copy .info when cropping
|
||||
if isnonblank(t):
|
||||
(page, palsel) = self.add(array('B', t.tostring()), ncolors)
|
||||
loads += [" GD.xsprite(x, y, %d, %d, %d, %d, rot, jk);" % (x * 16 - center[0], y * 16 - center[1], page, palset[palsel])]
|
||||
if loads:
|
||||
print >>self.hh, " case %d:" % spr
|
||||
print >>self.hh, "\n".join(loads)
|
||||
print >>self.hh, " break;"
|
||||
|
||||
print >>self.hh, """ }\n}\n"""
|
||||
|
||||
def used(self):
|
||||
"""
|
||||
Return the contents of the ImageRAM, as an :class:`array.array` of type 'B'.
|
||||
The size of the array depends on the amount of data added, up to a limit
|
||||
of 16K.
|
||||
"""
|
||||
if self.nxtbit == 0:
|
||||
past = self.nxtpage
|
||||
else:
|
||||
past = self.nxtpage + 1
|
||||
return array('B', self.data[:256*past])
|
||||
|
||||
import math
|
||||
|
||||
def spectrum(specfile, cutoff = 64, volume = 255):
|
||||
"""
|
||||
Read an Audacity spectrum file and return a list of (frequency, amplitude)
|
||||
pairs, loudest first.
|
||||
|
||||
:param cutoff: length of the list of returned pairs
|
||||
:param volume: total volume of the returned pairs
|
||||
:rtype: list of tuples (frequency, amplitude) where frequency is a floating-point frequency in Hz, and amplitude in an integer amplitude.
|
||||
|
||||
This function can be used to create voice profiles for instruments
|
||||
and sounds. For example to load a choir sound, previously saved
|
||||
as ``choir.txt``::
|
||||
|
||||
for (i, (f, a)) in enumerate(spectrum("choir.txt")):
|
||||
gd.voice(i, 0, int(4 * f), a, a)
|
||||
|
||||
"""
|
||||
|
||||
snd = [[float(t) for t in l.split()] for l in open(specfile) if not "Freq" in l]
|
||||
snd = [(f,db) for (f,db) in snd if 40 < f < 8192]
|
||||
snd = sorted(snd, reverse=True, key=lambda t:t[1])
|
||||
top = snd[:cutoff]
|
||||
amps = [(f,math.pow(2, .1 * db)) for (f, db) in top]
|
||||
samps = sum([a for (f,a) in amps])
|
||||
return [(f, int(volume * a / samps)) for (f, a) in amps]
|
||||
|
||||
__all__ = [ "encode", "dump", "palettize", "getpal", "ImageRAM", "spectrum", ]
|
||||
48
python/gameduino/registers.py
Normal file
48
python/gameduino/registers.py
Normal file
@ -0,0 +1,48 @@
|
||||
RAM_PIC = 0x0000 # Screen Picture, 64 x 64 = 4096 bytes
|
||||
RAM_CHR = 0x1000 # Screen Characters, 256 x 16 = 4096 bytes
|
||||
RAM_PAL = 0x2000 # Screen Character Palette, 256 x 8 = 2048 bytes
|
||||
|
||||
IDENT = 0x2800
|
||||
REV = 0x2801
|
||||
FRAME = 0x2802
|
||||
VBLANK = 0x2803
|
||||
SCROLL_X = 0x2804
|
||||
SCROLL_Y = 0x2806
|
||||
JK_MODE = 0x2808
|
||||
J1_RESET = 0x2809
|
||||
SPR_DISABLE = 0x280a
|
||||
SPR_PAGE = 0x280b
|
||||
IOMODE = 0x280c
|
||||
|
||||
BG_COLOR = 0x280e
|
||||
SAMPLE_L = 0x2810
|
||||
SAMPLE_R = 0x2812
|
||||
|
||||
SCREENSHOT_Y = 0x281e
|
||||
|
||||
PALETTE16A = 0x2840 # 16-color palette RAM A, 32 bytes
|
||||
PALETTE16B = 0x2860 # 16-color palette RAM B, 32 bytes
|
||||
PALETTE4A = 0x2880 # 4-color palette RAM A, 8 bytes
|
||||
PALETTE4B = 0x2888 # 4-color palette RAM A, 8 bytes
|
||||
COMM = 0x2890 # Communication buffer
|
||||
COLLISION = 0x2900 # Collision detection RAM, 256 bytes
|
||||
VOICES = 0x2a00 # Voice controls
|
||||
J1_CODE = 0x2b00 # J1 coprocessor microcode RAM
|
||||
SCREENSHOT = 0x2c00 # screenshot line RAM
|
||||
|
||||
RAM_SPR = 0x3000 # Sprite Control, 512 x 4 = 2048 bytes
|
||||
RAM_SPRPAL = 0x3800 # Sprite Palettes, 4 x 256 = 2048 bytes
|
||||
RAM_SPRIMG = 0x4000 # Sprite Image, 64 x 256 = 16384 bytes
|
||||
|
||||
def RGB(r, g, b):
|
||||
""" Return the 16-bit hardware encoding of color (R,G,B).
|
||||
|
||||
:param R: red value 0-255
|
||||
:param G: green value 0-255
|
||||
:param B: blue value 0-255
|
||||
:rtype: int
|
||||
"""
|
||||
return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)
|
||||
|
||||
TRANSPARENT = (1 << 15)
|
||||
|
||||
130
python/gameduino/remote.py
Normal file
130
python/gameduino/remote.py
Normal file
@ -0,0 +1,130 @@
|
||||
"""
|
||||
gameduino.remote - remote interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The remote interface lets Python scripts read and write
|
||||
Gameduino memory, via the USB connection and a
|
||||
simple client running on the Arduino.
|
||||
|
||||
The remote interface can be more convenient than compiling and uploading a
|
||||
Sketch when developing media and coprocessor microprograms::
|
||||
|
||||
import gameduino.remote
|
||||
gd = gameduino.remote.Gameduino("/dev/ttyUSB0", 115200)
|
||||
gd.ascii()
|
||||
gd.putstr(0, 5, "Hello from Python")
|
||||
|
||||
The Gameduino in this module is similar to the one in :mod:`gameduino.sim`.
|
||||
|
||||
Because this module uses USB serial interface to communicate with the Arduino,
|
||||
it requires the `PySerial module <http://pyserial.sourceforge.net/>`_.
|
||||
|
||||
.. image:: remote.png
|
||||
|
||||
The Arduino runs a simple program ``memloader`` that
|
||||
listens for serial commands and accesses Gameduino memory.
|
||||
"""
|
||||
|
||||
import struct
|
||||
import serial
|
||||
import time
|
||||
import array
|
||||
|
||||
from gameduino.registers import *
|
||||
from gameduino.base import BaseGameduino
|
||||
|
||||
class Gameduino(BaseGameduino):
|
||||
|
||||
def __init__(self, usbport, speed):
|
||||
self.ser = serial.Serial(usbport, speed)
|
||||
time.sleep(2)
|
||||
assert self.rd(IDENT) == 0x6d, "Missing IDENT"
|
||||
self.mem = array.array('B', [0] * 32768)
|
||||
self.coldstart()
|
||||
|
||||
def wrstr(self, a, s):
|
||||
if not isinstance(s, str):
|
||||
s = s.tostring()
|
||||
self.mem[a:a+len(s)] = array.array('B', s)
|
||||
for i in range(0, len(s), 255):
|
||||
sub = s[i:i+255]
|
||||
ff = struct.pack(">BH", len(sub), 0x8000 | (a + i)) + sub
|
||||
self.ser.write(ff)
|
||||
|
||||
def rd(self, a):
|
||||
""" Read byte at address ``a`` """
|
||||
ff = struct.pack(">BH", 1, a)
|
||||
self.ser.write(ff)
|
||||
return ord(self.ser.read(1))
|
||||
|
||||
def rdstr(self, a, n):
|
||||
"""
|
||||
Read ``n`` bytes starting at address ``a``
|
||||
|
||||
:rtype: string of length ``n``.
|
||||
"""
|
||||
r = ""
|
||||
while n:
|
||||
cnt = min(255, n)
|
||||
ff = struct.pack(">BH", cnt, a)
|
||||
self.ser.write(ff)
|
||||
r += self.ser.read(cnt)
|
||||
a += cnt
|
||||
n -= cnt
|
||||
return r
|
||||
|
||||
def waitvblank(self):
|
||||
while self.rd(VBLANK) == 1:
|
||||
pass
|
||||
while self.rd(VBLANK) == 0:
|
||||
pass
|
||||
|
||||
def linecrc(self, y):
|
||||
self.ser.write(struct.pack(">BBH", 0, ord('L'), y))
|
||||
return struct.unpack(">L", self.ser.read(4))[0]
|
||||
|
||||
def coll(self):
|
||||
"""
|
||||
Return the 256 bytes of COLLISION RAM.
|
||||
|
||||
:rtype: list of byte values.
|
||||
"""
|
||||
self.ser.write(struct.pack(">BB", 0, ord('c')))
|
||||
return array.array('B', self.ser.read(256)).tolist()
|
||||
|
||||
def collcrc(self):
|
||||
self.ser.write(struct.pack(">BB", 0, ord('C')))
|
||||
return struct.unpack(">L", self.ser.read(4))[0]
|
||||
|
||||
def memcrc(self, a, s):
|
||||
self.ser.write(struct.pack(">BBHH", 0, ord('M'), a, s))
|
||||
return struct.unpack(">L", self.ser.read(4))[0]
|
||||
|
||||
def _im(self):
|
||||
"""
|
||||
Return the current screen as a 400x300 RGB PIL Image::
|
||||
|
||||
>>> import gameduino.sim
|
||||
>>> gd = gameduino.sim.Gameduino()
|
||||
>>> gd.im().save("screenshot.png")
|
||||
"""
|
||||
import Image
|
||||
fi = Image.new("RGB", (400,300))
|
||||
for y in range(300):
|
||||
self.wr16(SCREENSHOT_Y, 0x8000 | y)
|
||||
while (self.rd16(SCREENSHOT_Y) & 0x8000) == 0:
|
||||
pass
|
||||
ld = array.array('H', self.rdstr(SCREENSHOT, 800))
|
||||
r = [8 * (31 & (v >> 10)) for v in ld]
|
||||
g = [8 * (31 & (v >> 5)) for v in ld]
|
||||
b = [8 * (31 & (v >> 0)) for v in ld]
|
||||
rgb = sum(zip(r,g,b), ())
|
||||
li = Image.fromstring("RGB", (400,1), array.array('B', rgb).tostring())
|
||||
fi.paste(li, (0, y))
|
||||
self.wr16(SCREENSHOT_Y, 0)
|
||||
return fi
|
||||
|
||||
|
||||
import array
|
||||
def readarray(filename):
|
||||
return array.array('B', open(filename).read())
|
||||
274
python/gameduino/sim.py
Normal file
274
python/gameduino/sim.py
Normal file
@ -0,0 +1,274 @@
|
||||
"""
|
||||
gameduino.sim - simple simulator
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Gameduino simulator can simulate some aspects of Gameduino hardware, both video and audio.
|
||||
It can be a useful tool for previewing media before loading on actual hardware.
|
||||
|
||||
The Gameduino in this module is similar to the one in :mod:`gameduino.remote`::
|
||||
|
||||
import gameduino
|
||||
import gameduino.prep as gdprep
|
||||
import gameduino.sim as gdsim
|
||||
|
||||
im = Image.open("platformer.png").convert("RGB")
|
||||
(picd,chrd,pald) = gdprep.encode(im)
|
||||
gd = gdsim.Gameduino()
|
||||
gd.wrstr(gameduino.RAM_PIC, picd)
|
||||
gd.wrstr(gameduino.RAM_CHR, chrd)
|
||||
gd.wrstr(gameduino.RAM_PAL, pald)
|
||||
gd.im().save("preview.png")
|
||||
|
||||
The simulator can produce screenshots (:meth:`Gameduino.im`), generate
|
||||
single-note sounds (:meth:`Gameduino.writewave`), and simulate collision RAM
|
||||
(:meth:`Gameduino.coll`). It does not currently simulate the coprocessor.
|
||||
|
||||
"""
|
||||
|
||||
import struct
|
||||
import time
|
||||
import array
|
||||
import math
|
||||
import itertools
|
||||
import wave
|
||||
import binascii
|
||||
|
||||
import Image
|
||||
|
||||
from gameduino.registers import *
|
||||
from gameduino.base import BaseGameduino
|
||||
|
||||
def sum512(a, b):
|
||||
return 511 & (a + b)
|
||||
def s9(vv):
|
||||
vv &= 0x1ff
|
||||
if vv > 400:
|
||||
vv -= 512;
|
||||
return vv
|
||||
|
||||
class Gameduino(BaseGameduino):
|
||||
"""
|
||||
The Gameduino object simulates some aspects of the Gameduino hardware. For example::
|
||||
|
||||
>>> import gameduino
|
||||
>>> import gameduino.sim as gdsim
|
||||
>>> gd = gdsim.Gameduino()
|
||||
>>> print hex(gd.rd(gameduino.IDENT))
|
||||
0x6d
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.mem = array.array('B', [0] * 32768)
|
||||
self.mem[IDENT] = 0x6d
|
||||
self.coldstart()
|
||||
|
||||
def wrstr(self, a, s):
|
||||
if not isinstance(s, str):
|
||||
s = s.tostring()
|
||||
self.mem[a:a+len(s)] = array.array('B', s)
|
||||
|
||||
def rd(self, a):
|
||||
""" Read byte at address ``a`` """
|
||||
return self.mem[a]
|
||||
|
||||
def rdstr(self, a, n):
|
||||
"""
|
||||
Read ``n`` bytes starting at address ``a``
|
||||
|
||||
:rtype: string of length ``n``.
|
||||
"""
|
||||
return self.mem[a:a+n].tostring()
|
||||
|
||||
def writewave(self, duration, dst):
|
||||
"""
|
||||
Write the simulated output of the sound system to a wave file
|
||||
|
||||
:param duration: length of clip in seconds
|
||||
:param dst: destination wave filename
|
||||
"""
|
||||
sintab = [int(127 * math.sin(2 * math.pi * i / 128.)) for i in range(128)]
|
||||
nsamples = int(8000 * duration)
|
||||
master = [i/8000. for i in range(nsamples)]
|
||||
lacc = [0] * nsamples
|
||||
racc = [0] * nsamples
|
||||
for v in range(64):
|
||||
if v == self.rd(RING_START):
|
||||
print v, max(lacc)
|
||||
ring = [s/256 for s in lacc]
|
||||
lacc = [0] * nsamples
|
||||
racc = [0] * nsamples
|
||||
|
||||
(freq,la,ra) = struct.unpack("<HBB", self.rdstr(VOICES + 4 * v, 4))
|
||||
if la or ra:
|
||||
tone = [sintab[int(m * freq * 32) & 0x7f] for m in master]
|
||||
if self.rd(RING_START) <= v < self.rd(RING_END):
|
||||
lacc = [o + la * (r * t) / 256 for (o,r,t) in zip(lacc, ring, tone)]
|
||||
racc = [o + ra * (r * t) / 256 for (o,r,t) in zip(racc, ring, tone)]
|
||||
else:
|
||||
lacc = [o + la * t for (o,t) in zip(lacc, tone)]
|
||||
racc = [o + ra * t for (o,t) in zip(racc, tone)]
|
||||
merged = [None,None] * nsamples
|
||||
merged[0::2] = lacc
|
||||
merged[1::2] = racc
|
||||
raw = array.array('h', merged)
|
||||
w = wave.open(dst, "wb")
|
||||
w.setnchannels(2)
|
||||
w.setsampwidth(2)
|
||||
w.setframerate(8000)
|
||||
w.writeframesraw(raw)
|
||||
w.close()
|
||||
|
||||
def bg(self, lines = range(512)):
|
||||
bg_color = self.rd16(BG_COLOR) & 0x7fff
|
||||
glyphs = []
|
||||
for i in range(256):
|
||||
pals = array.array('H', self.mem[RAM_PAL + 8 * i:RAM_PAL + 8 * i + 8].tostring())
|
||||
for j in range(4):
|
||||
if pals[j] & 0x8000:
|
||||
pals[j] = bg_color
|
||||
glyph = []
|
||||
for y in range(8):
|
||||
for x in range(8):
|
||||
pix = 3 & (self.mem[RAM_CHR + 16 * i + 2 * y + (x / 4)] >> [6,4,2,0][x&3])
|
||||
glyph.append(pals[pix])
|
||||
glyphs.append(glyph)
|
||||
img = {}
|
||||
for y in lines:
|
||||
line = []
|
||||
for x in range(512):
|
||||
c = self.mem[RAM_PIC + 64 * (y >> 3) + (x >> 3)]
|
||||
line.append(glyphs[c][8 * (y & 7) + (x & 7)])
|
||||
img[y] = line
|
||||
return img
|
||||
|
||||
def sprfetch(self, img, pal, rot, x, y):
|
||||
if rot & 1:
|
||||
exo,eyo = y,x
|
||||
else:
|
||||
exo,eyo = x,y
|
||||
if rot & 2:
|
||||
exo = 15 - exo
|
||||
if rot & 4:
|
||||
eyo = 15 - eyo
|
||||
ix = self.rd(RAM_SPRIMG + 256 * img + 16 * eyo + exo)
|
||||
if (pal & 0xc) == 0:
|
||||
pix = self.rd16(RAM_SPRPAL + 512 * (pal & 3) + 2 * ix)
|
||||
elif (pal & 0xc) == 4:
|
||||
nyb = 15 & (ix >> [0,4][1 & (pal >> 1)])
|
||||
pix = self.rd16(PALETTE16A + 32 * (pal & 1) + 2 * nyb)
|
||||
else:
|
||||
nyb = 3 & (ix >> [0,2,4,6][3 & (pal >> 1)])
|
||||
pix = self.rd16(PALETTE4A + 8 * (pal & 1) + 2 * nyb)
|
||||
return pix
|
||||
|
||||
def spr_page(self):
|
||||
return RAM_SPR + 1024 * (self.rd(SPR_PAGE) & 1)
|
||||
|
||||
def sp(self, y, line):
|
||||
if self.rd(SPR_DISABLE) & 1:
|
||||
return line
|
||||
page = self.spr_page()
|
||||
for i in range(256):
|
||||
sprval = self.rd32(page + 4 * i)
|
||||
sx = s9(sprval)
|
||||
sy = s9(sprval >> 16)
|
||||
simg = (sprval >> 25) & 63
|
||||
spal = (sprval >> 12) & 15
|
||||
srot = (sprval >> 9) & 7
|
||||
yo = y - sy
|
||||
if 0 <= yo < 16:
|
||||
for xo in range(16):
|
||||
if 0 <= (sx + xo) < 400:
|
||||
pix = self.sprfetch(simg, spal, srot, xo, yo)
|
||||
if pix < 32768:
|
||||
line[sx + xo] = pix
|
||||
return line
|
||||
def coll(self):
|
||||
"""
|
||||
Return the 256 bytes of COLLISION RAM.
|
||||
|
||||
:rtype: list of byte values.
|
||||
"""
|
||||
coll = 256 * [0xff]
|
||||
page = self.spr_page()
|
||||
jkmode = (self.rd(JK_MODE) & 1) != 0
|
||||
if 0 == (self.rd(SPR_DISABLE) & 1):
|
||||
yocc = [[] for i in range(300)]
|
||||
for i in range(256):
|
||||
sprval = self.rd32(page + 4 * i)
|
||||
sy = s9(sprval >> 16)
|
||||
for j in range(16):
|
||||
if 0 <= (sy + j) < 300:
|
||||
yocc[sy + j].append(i)
|
||||
for y in range(300):
|
||||
tag = [None] * 400
|
||||
jk = [None] * 400
|
||||
for i in yocc[y]:
|
||||
sprval = self.rd32(page + 4 * i)
|
||||
sy = s9(sprval >> 16)
|
||||
yo = y - sy
|
||||
if 0 <= yo < 16:
|
||||
sx = s9(sprval)
|
||||
simg = (sprval >> 25) & 63
|
||||
spal = (sprval >> 12) & 15
|
||||
srot = (sprval >> 9) & 7
|
||||
sjk = (sprval >> 31)
|
||||
for xo in range(16):
|
||||
x = sx + xo
|
||||
if 0 <= x < 400:
|
||||
if self.sprfetch(simg, spal, srot, xo, yo) < 32768:
|
||||
if tag[x] != None:
|
||||
if (not jkmode) or (jk[x] != sjk):
|
||||
coll[i] = tag[x]
|
||||
tag[x] = i
|
||||
jk[x] = sjk
|
||||
return coll
|
||||
|
||||
def screen(self, lines, w = 400):
|
||||
sx = self.rd16(SCROLL_X) & 511
|
||||
sy = self.rd16(SCROLL_Y)
|
||||
bg = self.bg([sum512(y, sy) for y in lines])
|
||||
def wrapx(l):
|
||||
return (l + l)[sx:sx+w]
|
||||
return dict([(y, self.sp(y, wrapx(bg[sum512(y, sy)]))) for y in lines])
|
||||
|
||||
def _im(self):
|
||||
return self._imwh(400, 300)
|
||||
|
||||
def fullim(self):
|
||||
""" Return the entire 512x512 pixel screen image """
|
||||
return _imwh(512, 512)
|
||||
|
||||
def _imwh(self, w, h):
|
||||
import Image
|
||||
fi = Image.new("RGB", (w, h))
|
||||
lines = self.screen(range(h), w)
|
||||
for y in range(h):
|
||||
ld = lines[y]
|
||||
r = [8 * (31 & (v >> 10)) for v in ld]
|
||||
g = [8 * (31 & (v >> 5)) for v in ld]
|
||||
b = [8 * (31 & (v >> 0)) for v in ld]
|
||||
rgb = sum(zip(r,g,b), ())
|
||||
li = Image.fromstring("RGB", (w,1), array.array('B', rgb).tostring())
|
||||
fi.paste(li, (0, y))
|
||||
return fi
|
||||
|
||||
def linecrc(self, y):
|
||||
line = array.array('H', self.screen([y])[y]).tostring()
|
||||
return 0xffffffff & binascii.crc32(line)
|
||||
|
||||
def collcrc(self):
|
||||
return 0xffffffff & binascii.crc32(array.array('B', self.coll()).tostring())
|
||||
|
||||
def memcrc(self, a, s):
|
||||
return 0xffffffff & binascii.crc32(self.mem[a:a+s])
|
||||
|
||||
def memory(self):
|
||||
""" Returns current image of memory as a 32768 byte string """
|
||||
return self.mem.tostring()
|
||||
|
||||
def readarray(filename):
|
||||
return array.array('B', open(filename).read())
|
||||
|
||||
|
||||
__all__ = [ "Gameduino" ]
|
||||
4
python/go
Normal file
4
python/go
Normal file
@ -0,0 +1,4 @@
|
||||
sudo python setup.py install || exit
|
||||
# python remoteunit.py /dev/ttyUSB0 ; exit
|
||||
python unit.py TestGameduino.test_471fcf9e || exit
|
||||
# python randoms.py /dev/ttyUSB0
|
||||
BIN
python/platformer.png
Normal file
BIN
python/platformer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
190
python/randoms.py
Normal file
190
python/randoms.py
Normal file
@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import time
|
||||
import math
|
||||
import array
|
||||
import random
|
||||
|
||||
import gameduino
|
||||
import gameduino.remote
|
||||
import gameduino.sim
|
||||
|
||||
from duplicator import Duplicator
|
||||
|
||||
random.seed(10)
|
||||
|
||||
def read_y(y):
|
||||
gd.wr16(gameduino.SCREENSHOT_Y, 0x8000 | y)
|
||||
gd.waitvblank()
|
||||
gd.waitvblank()
|
||||
line = "".join([gd.rdstr(gameduino.SCREENSHOT + i, 200) for i in range(0, 800, 200)])
|
||||
gd.wr16(gameduino.SCREENSHOT_Y, 0)
|
||||
return array.array('H', line).tolist()
|
||||
|
||||
def sling(n):
|
||||
n1s = random.randrange(n + 1)
|
||||
return sum([(1 << i) for i in random.sample(range(n), n1s)])
|
||||
|
||||
def r(n):
|
||||
return random.randrange(n)
|
||||
|
||||
def randbytes(n):
|
||||
return array.array('B', [r(256) for i in range(n)])
|
||||
|
||||
def matches(r):
|
||||
return r[0] == r[1]
|
||||
|
||||
class TestRegime(object):
|
||||
def __init__(self, dd):
|
||||
self.dd = dd
|
||||
assert matches(dd.rd(gameduino.IDENT))
|
||||
self.dd.microcode(open("../synth/sketches/j1firmware/thrasher.binle").read())
|
||||
self.setup()
|
||||
|
||||
def scramble(self):
|
||||
""" Scramble all registers and memories """
|
||||
for rg in self.reg8s:
|
||||
self.dd.wr(rg, r(2**8))
|
||||
for rg in self.reg16s:
|
||||
self.dd.wr16(rg, r(2**16))
|
||||
for a,s in self.memories:
|
||||
self.dd.wrstr(a, randbytes(s))
|
||||
|
||||
def setup(self):
|
||||
self.scramble()
|
||||
|
||||
def cycle(self):
|
||||
for c in xrange(1000000):
|
||||
print "Cycle", c
|
||||
for (area,size) in random.sample(self.memories, r(len(self.memories))):
|
||||
dat = randbytes(1 + sling(6))
|
||||
if len(dat) == size:
|
||||
a = area
|
||||
else:
|
||||
a = area + random.randrange(0, size - len(dat))
|
||||
self.dd.wrstr(a, dat)
|
||||
if r(2) == 0 and self.reg16s:
|
||||
self.dd.wr16(random.choice(self.reg16s), random.getrandbits(16))
|
||||
if r(2) == 0 and self.reg8s:
|
||||
self.dd.wr(random.choice(self.reg8s), random.getrandbits(8))
|
||||
|
||||
for (y, (e,a)) in [(y, self.dd.linecrc(y)) for y in self.checklines()]:
|
||||
if e != a:
|
||||
print "mismatch at line", y, (e,a)
|
||||
e = gameduino.sim.screen([y])[y]
|
||||
a = read_y(y)
|
||||
print "expected", e
|
||||
print "actual", a
|
||||
print set([(ee != aa) for (ee,aa) in zip(e,a)])
|
||||
print 'y', self.dd.linecrc(y)
|
||||
sys.exit(1)
|
||||
a,s = random.choice(self.memories)
|
||||
if r(5) == 0:
|
||||
assert matches(self.dd.rd(a + r(s)))
|
||||
if r(5) == 0:
|
||||
assert matches(self.dd.memcrc(a, s))
|
||||
|
||||
if not matches(self.dd.collcrc()):
|
||||
def s9(vv):
|
||||
vv &= 0x1ff
|
||||
if vv > 400:
|
||||
vv -= 512;
|
||||
return vv
|
||||
|
||||
if 0:
|
||||
page = self.dd.spr_page()[0]
|
||||
for i in range(256):
|
||||
sprval = gdsim.rd32(page + 4 * i)
|
||||
sx = s9(sprval)
|
||||
sy = s9(sprval >> 16)
|
||||
simg = (sprval >> 25) & 63
|
||||
spal = (sprval >> 12) & 15
|
||||
srot = (sprval >> 9) & 7
|
||||
sjk = (sprval >> 31)
|
||||
print "%3d: x=%3d y=%3d img=%2d pal=%d rot=%d jk=%d" % (i, sx, sy, simg, spal, srot, sjk)
|
||||
(e,a) = self.dd.coll()
|
||||
print 'collcrc', self.dd.collcrc()
|
||||
import binascii
|
||||
print 'e crc', 0xffffffff & binascii.crc32(array.array('B', e).tostring())
|
||||
print 'a crc', 0xffffffff & binascii.crc32(array.array('B', a).tostring())
|
||||
for i in range(256):
|
||||
print "%3d: e=%3d a=%3d" % (i, e[i], a[i])
|
||||
sys.exit(1)
|
||||
# gdsim.im().save("p%04d.png" % c)
|
||||
|
||||
class FullchipRegime(TestRegime):
|
||||
reg16s = [gameduino.SCROLL_X, gameduino.SCROLL_Y, gameduino.BG_COLOR, gameduino.SAMPLE_L, gameduino.SAMPLE_R]
|
||||
reg8s = [gameduino.IDENT,
|
||||
gameduino.REV,
|
||||
gameduino.SPR_PAGE,
|
||||
gameduino.JK_MODE,
|
||||
gameduino.SPR_DISABLE,
|
||||
gameduino.IOMODE]
|
||||
memories = [
|
||||
(gameduino.RAM_PIC, 10 * 1024),
|
||||
(gameduino.RAM_SPR, 2048),
|
||||
(gameduino.RAM_SPRPAL, 2048),
|
||||
(gameduino.RAM_SPRIMG, 16384),
|
||||
(gameduino.PALETTE16A, 64),
|
||||
(gameduino.PALETTE4A, 64),
|
||||
(gameduino.VOICES, 256),
|
||||
# (gameduino.IDENT, 64), # register file
|
||||
]
|
||||
def checklines(self):
|
||||
return [0, 299] + random.sample(range(1, 299), 2)
|
||||
|
||||
class SpriteRegime(TestRegime):
|
||||
reg16s = []
|
||||
reg8s = [gameduino.JK_MODE,
|
||||
gameduino.SPR_PAGE]
|
||||
memories = [
|
||||
(gameduino.RAM_SPR, 2048),
|
||||
(gameduino.RAM_SPRPAL, 2048),
|
||||
# (gameduino.RAM_SPRIMG, 16384),
|
||||
(gameduino.PALETTE16A, 64),
|
||||
(gameduino.PALETTE4A, 64),
|
||||
(gameduino.VOICES, 256),
|
||||
]
|
||||
|
||||
def setup(self):
|
||||
self.scramble()
|
||||
patt = (
|
||||
"0101010101010101"
|
||||
"1222222222222220"
|
||||
"0222222222222221"
|
||||
"1222222222222220"
|
||||
"0222222222222221"
|
||||
"1222222222222220"
|
||||
"0222222222222221"
|
||||
"1222222222222220"
|
||||
"0222222222222221"
|
||||
"1222222222222220"
|
||||
"0222222222222221"
|
||||
"1222222222222220"
|
||||
"0222222222222221"
|
||||
"1222222222222220"
|
||||
"0222222222222221"
|
||||
"1010101010101010" )
|
||||
def expand(c):
|
||||
c = int(c)
|
||||
return c + 4 * c + 16 * c + 64 * c
|
||||
|
||||
image = array.array('B', [expand(c) for c in patt])
|
||||
for i in range(64):
|
||||
self.dd.wrstr(gameduino.RAM_SPRIMG + 256 * i, image);
|
||||
self.dd.microcode(open("../synth/sketches/j1firmware/thrasher.binle").read())
|
||||
|
||||
def checklines(self):
|
||||
return []
|
||||
|
||||
def main():
|
||||
gdsim = gameduino.sim.Gameduino()
|
||||
gd = gameduino.remote.Gameduino(sys.argv[1], 115200)
|
||||
dd = Duplicator((gdsim, gd))
|
||||
# rr = SpriteRegime(dd)
|
||||
rr = FullchipRegime(dd)
|
||||
rr.cycle()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user