I loaded up the new T4 image on a PropBOE - works fine.
And then wanted to try my WS2812 play,
but discovered there is still some functionality not implemented in EXTEND
Like .. ORG, BYTE, #P8, &12.13.14.15 number parsing
I think it makes little sense to rewrite my code - which I could of course -
to work around those missing functions
or extend the EXTEND ;-) - while ORG, BYTE ... probably could easily be moved from EXTEND-V3, number parsing integrates closer to the new kernel.
So I better stay with T3 for now then.
V4 is still case sensitive as V3 used a retry after conversion to uppercase. I've simply used "byte" and "org" in lower case while I've also kept number processing lean and mean so it doesn't do any additional processing (for now). But the WS2812 stuff works well, in fact it was one of the first things I tried out. Have a look at EASYFILE and EASYNET for examples of the current usage.
22 == *LED
long rgb --- bbrrgg
: LED DUP 8>> SWAP >B 16 << + rgb ! rgb 3 *LED MASK DUP OUTCLR 4 COGREG! [WS2812] RUNMOD ;
: DEMO 0 LED 0 BEGIN DUP @ 3 RUNMOD 500 ms 1+ KEY UNTIL DROP ;
BTW - (byte, word, long) can't take CSVs yet, only a single definition and (bytes, words, longs) in V3 would always long align whereas in V4 words aligns to words and bytes doesn't align. If you don't want any alignment then use DS to create the structure. I will try to update the document but basically I'm not trying to complicate the kernel any more than I need to while I experiment.
Number parsing in V4 is handled at the character input level where it tries to build a number while building a word. If the number of digits = the number of characters then there is no need to check it any further or search the dictionary, it is pushed onto the stack. Whether it is accepted as a digit depends upon the #/$/% prefix or current base if no prefix is used. There is no reason though that I cannot process the "number" further if it is in V3 form with intermixed with symbols.
I will probably implement non-volatile variables but not in the C sense but as variables that are backed up with code in EEPROM whereas most variables are in the reclaimed hub RAM area that is occupied by the kernel and serial cog images in EEPROM and so cannot be backed up there. V3 had data and code mixed which was easy to backup but also took up code memory and if a variable was overrun it certainly caused problems.
BTW @mjb - I thought you would have been the one person to go check the "documentation", that is the Forth source files such as EXTEND etc.
EDIT: My character input routine already allowed for digit separators so I assigned a few codes etc. Now you can type #P16 or 10,000 or 10_0000 etc. Also added aliases for byte/word/long etc
Separators are:
BTW @mjb - I thought you would have been the one person to go check the "documentation", that is the Forth source files such as EXTEND etc.
@Peter - yes I felt 'guilty' not having done my homework, when I read your response - usually I read before I ask ...
I had checked EXTEND ... but only 5 minutes - and this is not enough for all the changes ;-)
I will be catching up.
Unfortunately I have little free time for Tachyon right now.
The project here turns out far bigger than originally planned.
Working on the plans for a 250m³ water tank and a ~ 3 million liter/3000m³ 'lake'.
And you have to control everything here in Spain - even the mixture of the concrete, so they do it right.
With the climate change southern spain is getting even more dry these days.
Province Almeria is at 7% of their storage capacity ... we are a bit better here.
EDIT: My character input routine already allowed for digit separators so I assigned a few codes etc. Now you can type #P16 or 10,000 or 10_0000 etc. Also added aliases for byte/word/long etc
Separators are:
For the sake of a handful of bytes I have implemented special character literals such as ^Y which returns the control character code or 'Y' with the ASCII code. Note that V3 started off with "Y" style but I changed this later on to use the tick character instead as I found it too confusing when I also had single character strings etc. TABLE is next along with "non-volatile" variables. I do have EASYNET running so I might just load up a board and stick it on tachyonforth.com later on for anyone to play with.
I noticed that by the time I was compiling EASYNET after EASYFILE and EXTEND that I needed to set the terminal line delay to 40ms. Not being happy with that I experimented with supplementing the dictionary search with LMM, scrubbed that, then a RUNMOD PASM module which was good but interfered with other RUNMODs when interactively testing.
So I squeezed all the required functionality into 21 longs (the maximum RUNMOD size) and now have this loaded automatically during a block mode source code load that starts with the TACHYON keyword and ends with END. Block load mode speeds up compilation by not echoing anything except errors and simply updating the line number prompt. During normal interactive mode it uses the slower but less invasive dictionary search so we get the best of both worlds.
With the fast dictionary search mode I can now set minicom to 3ms line delay at 921600 baud. Most of those lines of code have a lot more than one instruction and having 10 or more instructions on one line is not uncommon which is why it needs time to process all those searches.
Let's see if I can do better later on.
CODE:$486C x18028 bytes NAME:$4F5E x9378 bytes DATA:$7A03 x1011 bytes x1778 bytes free Data Stack (0)
( 0021 $486C ok ) SDC SDPINS
( 0022 $486C ok ) MOUNT
Mounted DA52.0000-BBC4.CD9E mkfs.fat DAWN FAT32 8031MB (4096/cluster)
( 0023 $486C ok ) ls-l
-rwxrwxrwx 1 502 500 1390 Dec 16 03:45 DUMPV4.FTH
-rwxrwxrwx 1 502 500 47765 Dec 15 22:02 EASYFILE.FTH
-rwxrwxrwx 1 502 500 52392 Dec 16 05:52 EASYNET.FTH
-rwxrwxrwx 1 502 500 23547 Dec 16 07:34 EXTEND.FTH
-rwxrwxrwx 1 502 500 1426 Dec 15 14:24 SEEDAWN.FTH
-rwxrwxrwx 1 502 500 200883 Dec 16 07:32 TACHYO~1.SPI
-rwxrwxrwx 1 502 500 117804 Jun 17 06:15 POPCORN.WAV
( 0024 $486C ok )
( 0025 $486C ok ) EASYNET
*** Tachyon Forth EASYNET Network Servers and EASYFILE File Server ***
... ready!
NETWORK STATUS:
LINK DOWN
HARDWARE: using WIZnet W5500 V4
SRC IP 194.168.000.150
MASK 255.255.255.000
GATEWAY 194.168.000.001
MAC 02.FF.D7.3C.5D.BE.
SKT HH:MM:SS MODE PORT DEST TXRD TXWR RXRD RXWR RXSZ IR STATUS IP ADDR
#1 07:05pm TCP 21 . . . . . 00 14 LISTEN
#3 07:05pm TCP 10001 . . . . . 00 14 LISTEN
#4 07:05pm TCP 80 . . . . . 00 14 LISTEN
* WEB, FTP, and TELNET servers running *
( 0026 $486C ok )
( 0027 $486C ok ) lsroms
*** ROMS ***
0848 VGA32x15
0308 HSUART
1900 F32
0196 MONO16
1900 F32
( 0028 $486C ok )
( 0017 $486C ok )
DICTIONARY WORDS @4F5E
EASYNET GO RESTART ?EASYNET netflgs fsave ?LED ?CTRLS lk ?HTTP #hskts GET HEAD GETPAGE GETTXT GETHTX ?CONTENT getsz GET$ CONTENT ?FTP REST STOR (RETR) R
ETR RNTO RNFR RNFR$ FTPMSG SIZE SENDFILE BLKSEND BUFSIZ blkpoll LIST ?DISCONNECT PWD CWD cwd$ CDUP MDTM FEAT SYST PASV #ftpmax #ftpmin PORT TYPE type PAS
S USER ECHOREQ GETFNAME dataport pass$ user$ .IPD COMMA .BYTEDEC GETTIME RESOLVE ?TELNET QUIT BYE constat CONNECT DISCONNECTED? DISCONNECT CONNECTED? DIS
CREQ disreq KEEPALIVE contd UpdateTXWR LANSKT FlushSkt MSG> <MSG msgstk MSGS msgs ledon ledcnt QUIET un UNKNOWN EASYNET.fth skt$ HTTP TELNET FTPDAT FTP N
ETMAN .SOCKETS ifconfig .SKT .SOCKET .SKTHD SWAPB .PTR .@SKTBUF .IP1 .IP .IPX .EMIT @SKTBUF sktbuf LREADSKT LSEND WBUFSZ WIZ !WIZ !TXBUFS !WIZIP oui2 !WI
ZIO WCOLD LANCON LANCONKEY LANCONEMIT LAN LANKEY LANEMIT LANSEND ?SEND ?SENDPOLL WAITSEND sendtimer autosend txsize txtime !TXWR @txwr txwr SetPORT PORT!
sDISCON? sCONNECTED? sCLOSING? sESTAB? sINACTIVE? sCLOSED? sRECV sSENDKEEP sSENDMAC sSEND sCLOSE sDISCON sCONNECT sLISTEN sOPEN PPPoE MACRAW IPRAW UDP T
CP CLOSED sMODE KEEPTMR RXWRITE RXREAD RXSIZE@ TXWRITE TXREAD TXFREE@ sTXMEM sRXMEM sPRO sSSIZE sDPORT sDIP! sDHAR! sPORT sSTAT sINTS sCMD! @SOCKET SKT@
SOCKET SKT socket &CON &DISCON &RECV &TIMEOUT &SENDOK UPORT UIP @RCR @RTR INTMASK INTS@ SIP MAC SUBNET GATEWAY wMODE @ports @wcold @mac @subnet @sip @gat
eway LWRITE LREAD vwrite vread L@ LW@ LC@ L! LW! LC! @RX @TX @SKT @COMMON ctrl! SKTBLK rdc wrc WPWRDN WRESET wizpins mySN myIP myGW &WNDI &WNCK &WNCS &WN
DO ALARM RIGHT$ GETRND NUMBER CON] [CON CONSOLE TRUE +POLL >UPPER LEDS LANLED READYLED W5500.fth SDC QV .FILES .FX .FILE ls-l ls .LIST (.LIST) (ls) lscnt
.UTIME .FNAME (SLIST) (DIR) DIR udir .DIR (.DIR) .ATR .PATH pwd cd$ cd cwd$ cat (cat) FPRINT$ FRUN FLOAD rm DELETE RENAME RENAME$ RW APPEND APPEND.BLK e
of -FERASE @RCD >|RCDSZ RCDSZ FMAKEOPEN$ FOPEN FOPEN$ FOPEN# mk FCREATE$ FCLOSE FOUTPUT >FILE FINPUT FILE> FPUTB FPUT FGET s! fkey FREM @FWRITE @FREAD fs
tat fwrite fread FFC@ FC@ FC! FILE@ FSECT@ FSIZE@ StartCluster CLUSTERS? CLUSTER@ @CLUSTER NextFreeDir .FTIME .FDATE .ASMONTH .FYEAR FSTAMP TIME@ DATE@ F
TIME! @DIR! FDATE! DECS DIR! DIR? dir$ @DIRBUF @FSIZE @FCLST @FDATE @FTIME @FCLSTH @ADATE @CDATE @CTIME @CMS @ATR @FEXT @FNAME >F83 fname$ FILE$ file$ ?S
DCARD ?MOUNT MOUNT .FAT READFAT32 CLUST>SECT @FAT2 @FAT1 @FAT @BOOT cwdsect @ROOT fboot dirbuf file diradr rootdir clshift mounted fatname volname serial
rootcl sect/fat sectors fats rsvd sect/clust byte/sect oemname fat32 fatptr parts SD XW@ XC! XC@ X! X@ XADR XADR! FLUSH WRSECT ACTIVE? SECTOR _SDWR SDWR
_SDRD SDRD TOKEN _!SD !SD ?SDTIMEOUT sdtimer SDDAT! MARKER? SDERR? STAT@ ACMD CMD SDCS RES@ !SDIO SDPINS SDBUSY &sdto SDCLK SD4@ SD2@ (SDRD) scanpos sca
ncnt scanch SD! SD@ _CARD? CARD? SDCMD sdcmd sdres sddst sdsrc SDERRLED SDBSYLED @FILE FILE# FILE SDBUF @SDBUF @scrc scrcs @sector sectors WRFLG @WRFLG w
rflgs filesel sdhc blklen card? crc sdbusy ucard sdrd sdwr sdsize sdpins ocr csd cid sdinfo =dtk BLKSIZ *SDCS @SDCS P1656 P8 DS EASYFILE.fth LOADCOG FIND
ROM NEXTROM lsroms .rom romsz roms .ES AUTORUN DUMPE DMPE EE BACKUP ?BACKUP CONBAUD EEPROM ECOPY EFILL ELOAD ESAVE ep ESAVEB ENDRD E! E@ EW@ EW! EC@ EC!
@EEWAIT EERD @EE eeadr FI2C@ I2C@ ackI2C@ I2C! I2C!? I2CSTOP I2CREST I2CSTART ?I2C I2CREST I2CSTART ?I2C i2cflg WWORDS .ATR MARGINS BOLD REVERSE ATR PLAI
N CURSOR ERLINE ERSCN CLS XY .PAR CUR PAPER COL PEN ESCB HOME ESC white cyan magenta blue yellow green red black MODPINS SETPINS SPIPINS MASK? @SPISCK @S
CL @CE @MISO @MOSI @SCK @CNT *SDA *SCL BLINK MUTE HZ KHZ MHZ HZCON FRQ DAC! BPIN APIN PLLDIV PLL DUTY DIFF CTR! CTRMODE NCO CTR@ CTR B A _ctr SEROUT SERB
AUD baudcnt .DEC PRINTDEC .DECX D. .DP .NUM PRINTNUM (.NUM) (SEP) RADIX> >RADIX RADIX radix .DT .DATE .TIME .DAY day date time OK !PCB RND (rnd) TIMEOUT
TIMEOUT? UCNT@ ms@ mscnt CNT@ STRING BREAK CASE SWITCH@ SWITCH uswitch LONGFILL C~~ W~~ ~~ C-- C++ W-- W++ -- ++ B>L B>W W>L W>B L>W BITS >W RELEASE LOCA
L X4 X3 X2 X1 @X locals AVG IN PIN@ OUT PIN! P! P@ SPR! VSCL VCFG PHSB PHSA FRQB FRQA CTRB CTRA DIRB DIRA OUTB OUTA INB INA CNT PAR SPR (FORGET) FORGET $
= COMPARE$ LOCATE$ $! COPY$ NULL$ boot delim lastkey CON ?POLL NULLOUT nout MOD @. <= => |< DS DS+ EX LONGS BYTES LONG WORD BYTE ORG PUBLIC PRIVATE UNSMU
DGE IMMEDIATE @HATR U@ U! ulong >| ?? PCB PCB$ FALSE CLKFREQ EXTEND.fth NOP DUP 2DUP OVER DROP 2DROP SWAP ROT -ROT NIP 3DROP ?DUP 3RD 4TH >R R> >L L> !RP
!SP AND ANDN OR XOR ROL ROR SHR >> 8>> SHL << 8<< 2/ 2* SAR REV MASK >N >B 9BITS 0= NOT 1+ 1- + - 2+ 4+ 2- MIN MAX * UM* U/ U/MOD / UM/MOD64 UM/MOD32 */
UM*/ ABS -NEGATE ?NEGATE NEGATE ADO DO LOOP +LOOP FOR NEXT BOUNDS I J K IX LEAVE IF ELSE THEN ENDIF BEGIN UNTIL AGAIN WHILE REPEAT C@ W@ @ C+! C! C@++ W
+! W! +! ! C~ W~ ~ SET? SET CLR CMOVE ERASE FILL <CMOVE RESET 0EXIT EXIT ?EXIT CALL JUMP BRANCH> (WAITPNE) RUNMOD (WAITPEQ) (EMIT) (EMITX) CMPSTR LOADMOD
COG@ COGREG COG! COGREG! COGREG@ COGINIT COGID REBOOT CLK CLKSET DELTA WAITCNT LAP .LAP CLOCK CLKIN CLKOUT OUTSET OUTCLR OUTPUTS INPUTS SHROUT SHRINP HI
GH LOW FLOAT SPIWRB SPIWR16 SPIWR SPIRD SPICE 0<> <> WITHIN U> = > < U< 0< HEX DECIMAL BINARY READBUF KEY WKEY (KEY) KEY! EMIT CLS SPACE SPACES EMITS BEL
L CR <CR> SPINNER .HEX .BYTE .WORD .LONG @PAD HOLD >CHAR #> <# # #S <D> PRINT$ CTYPE LEN$ U. .DEC .DP PRINT . ZPRINT CREATE CREATE$ GETWORD @WORD SEARCH
FINDSTR NFA>BFA CFA>NFA NFA>NFA @NAMES names WORDS ALLOT ALLOCATED HERE , || | EXECUTE VER .VER TACHYON END ECHO us ms seconds second DISCARD REG BUFFERS
KOLD DUMPX DUMP DUMPW DUMPL DUMPC DUMPA DUMPAW QD DEPTH .S DEBUG .FREE .STATS --- \ '' ( { } IFDEF IFNDEF " (") ." PRINT" (.") == org @org byte word lon
g bytes words longs ALIGNORG ALIGN : pub pri ; [C] ' ['] NFA' OFF ON -1 ALIAS GRAB [WS2812] [SDRD] [SDWR] [SPIO] dmm errors here there flags prompt autor
un keypoll uemit ukey base V4 *end*
A good compile speed will also help the dynamic loading of code/scripts and eventually the dynamic webserver, when I get back to it.
Having T4 running on the IoT5500+P8 might be a good reason to have a look at it again ...
btw: I discovered (by reading 'documentation' ;-) and trying it out ) -
that with 'a' 'ax works as well
so I was thinking instead of wasting bytes to check for the closing '
maybe to streamline it with the other use of ^a as 'a for single character literal instead of the use of closing '
could work as well ...
and make a cllear distinction from " a" single char string.
btw: I discovered (by reading 'documentation' ;-) and trying it out ) -
that with 'a' 'ax works as well
so I was thinking instead of wasting bytes to check for the closing '
maybe to streamline it with the other use of ^a as 'a for single character literal instead of the use of closing '
could work as well ...
and make a cllear distinction from " a" single char string.
Yes, the only checks it needs to make is the first character and the length so a '?' will work just as well as '?? etc but still needs to be 3 characters long. I think 'A' reads better than just 'A as that may be a pointer to some code fragment or something. If it's 3 characters and starts with a ' then it is a character literal or if it starts with a ^ and is 2 characters long then it is a control character literal.
A good compile speed will also help the dynamic loading of code/scripts and eventually the dynamic webserver, when I get back to it.
Having T4 running on the IoT5500+P8 might be a good reason to have a look at it again ...
btw: I discovered (by reading 'documentation' ;-) and trying it out ) -
that with 'a' 'ax works as well
so I was thinking instead of wasting bytes to check for the closing '
maybe to streamline it with the other use of ^a as 'a for single character literal instead of the use of closing '
could work as well ...
and make a cllear distinction from " a" single char string.
Oh yes the dynamic webserver <?fth ." Hello World MJB" ?> for T4.
@Peter, really neat to see EasyNet "up". Will you still be able to recover that estimated amount of memory now that you have it all loaded and running?
A good compile speed will also help the dynamic loading of code/scripts and eventually the dynamic webserver, when I get back to it.
Having T4 running on the IoT5500+P8 might be a good reason to have a look at it again ...
btw: I discovered (by reading 'documentation' ;-) and trying it out ) -
that with 'a' 'ax works as well
so I was thinking instead of wasting bytes to check for the closing '
maybe to streamline it with the other use of ^a as 'a for single character literal instead of the use of closing '
could work as well ...
and make a cllear distinction from " a" single char string.
Oh yes the dynamic webserver <?fth ." Hello World MJB" ?> for T4.
@Peter, really neat to see EasyNet "up". Will you still be able to recover that estimated amount of memory now that you have it all loaded and running?
Recovering hub RAM is easy once I implement my hybrid RAM/EEPROM dictionary where the entries in the EEPROM are fixed length entries with a maximum 12 character length suitable for a fast binary search. Despite all the loud noises I heard when I proposed this I am still amused that anyone would be worried about that. With everything loaded including the decompiler etc and with the dictionary still in RAM I ran a simple little dictionary analyzer that tallied up names of the same length, with zero representing the sum total. Have a look-
Recovering hub RAM is easy once I implement my hybrid RAM/EEPROM dictionary where the entries in the EEPROM are fixed length entries with a maximum 12 character length suitable for a fast binary search. Despite all the loud noises I heard when I proposed this I am still amused that anyone would be worried about that. With everything loaded including the decompiler etc and with the dictionary still in RAM I ran a simple little dictionary analyzer that tallied up names of the same length, with zero representing the sum total. Have a look-
I'm pretty sure that I won't mind choosing a better name and trimming that "one" entry of 13 characters
IF you do as you said before, just copying the words with 12 chars and less to EEPROM and
keeping the others - if there are any - in backed up RAM, then nothing is lost anyhow.
In LISP there is fasl (fast load), where source files are precompiled and can be loded in very fast without parsing the whole thing. If need be, this could be done here as well.
If it is done the simple way, the precompiled code would only load on the image it was created on,
but this would save any linking steps.
I don't see any problems moving one word from 13 to 12. A few compromises need to be made to maximize our tiny 32k space. At least for me and my fat forth style of coding, I need every byte I can get.
I don't see any problems moving one word from 13 to 12. A few compromises need to be made to maximize our tiny 32k space. At least for me and my fat forth style of coding, I need every byte I can get.
For my code I agree totally - I like short as well.
Some time ago when this question about a fixed length came up my argument was
only the gut feeling, that I do not like constraints ;-).
AND since FORTH is so wonderfully extensible it's interpreter can also be used to implement domain/problem specific vocabularies that might be given from outside - and 'could' exceed the 12 char limit.
Just remember how easy it was so implement NEMA? parsing.
Or have a look at how the FTP, Telnet and HTTP clients are implemented.
Luckily FTP uses only short max 6 char commands, that get defined as Tachyon words and
a little fiddling and the FTP handler is born.
Those wunderful options, that we of course do not know the use of today - is what I was talking.
AND when Peter said he will keep the variable length in RAM and move only the <= 12 words to EEPROM,
than I fully supported this - since now we have both benefits.
So we can eat the cake and keep it.
What more can you hope for.
AND if speed and memory really require it, then I am also fine with fixed 12 chars in RAM
IF we get a meaningful error message ;-)
BUT it does not look like it would really save memory.
Interesting thing I discovered when I added the TABLE definition which is essentially a variable in code spaces with zero bytes allocated is that I initially tried to add byte elements to the table as I would in V3 thus:
But it would crash every time although I could add word or long elements without any problems. Turns out that as I add each element which is added in code memory that this created a word alignment problem since the the number is compiled first as is normal for all Tachyon code even in interactive mode, then GRAB'ed by executing. V4 expects all code to be word aligned, even strings etc. If I wanted to allow for byte elements I had to compile it as a word first but flag that I had the high byte free so that the next byte element would simply GRAB and then store it's value in the previous byte location that had already been allocated. If the last byte was an odd element then it would simply waste the high byte of the word. Just thought I'd share that little gotcha.
The & prefix that I use for IP decimal byte notation has been added as well and besides IP style notation such as &192.168.0.150 which is much easier to enter than $C0A8.0096 the & is also useful for compacted I/O pin assignments that I use for SPI, SD cards, WIZnet chips etc. I pack 4 pins into a long usually assigned to a constant so that I can describe a board with a single constant at runtime. For instance I have these 4 constants that define the pins that are used for SD card interfacing for 4 different boards:
Which assigns the chip enable, the SD data out (MISO), the SD data in (MOSI), and the SD clock after which I can initialize the card and mount the FAT32 file system. Easy!
I'm working towards running some projects with V4 and so I'm filling in the blanks and making changes to suit etc and have just ported over my 20x4 character LCD module which is very comprehensive and as all Tachyon devices works transparently as if it were a serial output device responding to control characters and sequences etc in a similar manner to a serial terminal but of course with device specific control codes for big digits, contrast adjustment, back-lighting etc. This module was primarily where I was testing out the TABLE and table building words.
Here's a decompilation of the routine that handles character data, all variable addresses or constants 15-bits and under are compiled directly as a literal:
( 0077 $3A1C ok ) SEE LCDCHAR
35B8 $0001 (1)
35BA $7951 (31057)
35BC SET?
35BE OVER
35C0 $0030 (48)
35C2 $0039 (57)
35C4 WITHIN
35C6 AND
35C8 IF (35CE)
35CA DRAWBIG
35CC GOTO $35E2
35CE THEN
35CE LCDDAT
35D0 $794D (31053)
35D2 C++
35D4 $794D (31053)
35D6 C@
35D8 $0014 (20)
35DA =>
35DC IF (35E2)
35DE LCDCR
35E0 LCDLF
35E2 THEN
To kick V4 along I have a project where I need to control two or more commercial A/C units which at present have two separate and fiddly little control panels connected via RS485 up to a relay pcb in the A/C. The relay pcb doesn't really do much as it is a slave but does measure a thermistor in the return air that the existing control panel reads. These control panels are connected via 8-core twisted pair data cable with two pairs doubled up for +12V from the A/C and one pair for RS485 and one spare. Since the relays only really switch optos I plan to do away with the relay pcb and connect those four optos to four wires, one common, two for the thermistor, and one spare direct to my pcb which has a open-drain shift register driving two sets of four relays.
My control panel handles these two units via a 320x240 touch TFT screen with SSD2119 controllers that I happen to have that I interfaced to Tachyon back in the early days and were collecting dust but I have now upgraded all of that for V4. I plan to have additional sensors on RS485 using my ping-pong protocol.
Here's what the screen looks like so far.
Here's a snippet of code which displays the "LEDs".
--- display 8 virtual LEDS on the screen as a vertical column
pub LEDS ( leds -- ) 8 0 DO DUP 1 AND IF GREEN ELSE RED DIM THEN PEN 310 I 25 * 44 + 10 10 RECT 2/ LOOP DROP ;
BTW, V4 can do all this including FAT32 virtual memory and WIZnet servers etc - all in a standard 32k P1.
Practical application is what refines and defines a language or environment, and rather than a language looking for an application, Tachyon has always been driven by applications looking for a means to be implemented. Also engineering is about making things work with what we've got rather than saying if or when, so Tachyon is the "making things work" part of engineering, making "when" today, and "if" is. Benchmarks and popularity aren't much use if it doesn't cut the mustard since the language is there to help get the job done, and the job when done is not about the language. If debates were about how well an application is implemented, then debates about languages would be a moot point. The proof is in the pudding in that the result speaks for itself and is a far greater testament than opinions.
So I'm saying all this because I don't look at how much memory I have left, I just look at how much I can get done. If I need to do more I have options including moving the dictionary to EEPROM, running scripts or loading code modules from EEPROM/Flash/SD etc. We have "a bird in the hand", eight 32-bit CPUs waiting to be used, so why should we go pining for the P2 in the bush? What's worth more?
The only reason I ask is that my Tachyon is not very optimized and I tend to use it poorly still. I'm sure there is plenty of code space left for my humble needs if you are planning on using this version for your "big machine" build out. Curiosity only.
The only reason I ask is that my Tachyon is not very optimized and I tend to use it poorly still. I'm sure there is plenty of code space left for my humble needs if you are planning on using this version for your "big machine" build out. Curiosity only.
I had another look at the cleaned-up version of your garden program and immediately saw areas that could be removed or redone even though we refactored the code a lot. Take a look at this:
pub clearram
params ramlen ADO 0 I C! LOOP
;
that shouldn't even be a routine, just say:
params ramlen ERASE
Then right up above it you set defaults yet this is begging for a table of default values that you just CMOVE rather than hand picking each value.
I think the problem with coding is that it is fair enough you write it first to get it functional but even just a cursory revision of the flow of each routine itself would reveal some detail that can be combined or removed altogether. The other thing is being familiar with some of the built-in functions such as ~ W~ C~ for clearing variables so that rather than writing 0 myvar ! you could write myvar ~ instead. In V3 the first form didn't take up any more memory and was faster but in V4 it is desirable to write it second way,
However in saying all this I don't think your coding style itself would make it a memory hog although I do see lots and lots of messages embedded in the code. Perhaps if I reintroduce the EPRINT function which kept print strings in upper EEPROM then maybe that would help so I will have a look as I know that this might help elsewhere. I just want this function to act transparently so that we don't have to worry about cluttering the code with any settings other than switching it on.
BTW, my previous post was outlining my thinking in regards to Tachyon as I thought that if I go down the path of looking to see "how much memory is left over" then I would be painting myself into a corner as memory left over is memory wasted
BTW, my previous post was outlining my thinking in regards to Tachyon as I thought that if I go down the path of looking to see "how much memory is left over" then I would be painting myself into a corner as memory left over is memory wasted
we never waste free memory -
we find creative ways of filling it ;-)
and then with just a little more creativity we / you create space again ...
I like this :-)
V4 has been pressed into service the last couple of weeks as I bit the bullet with my current projects and now use this version. I find that there is nothing like some real life projects to get you to sharpen and customize the tools you are using, in this case Tachyon V4. I have it running on about 5 different boards with five different applications so this is helping me to find the bugs and fill in the holes.
Most of these apps are using the HSUART for ping-pong RS485 network too. I'd like to see F32 up and running too but I haven't had a real need to interface it properly yet, maybe that's a good job for a fellow Tachyonite?
I'm not sure how to even begin to integrate F32 with V4. One example would help. Where I'm stuck is the string float to hex representation to feed to F32 then back to string float output via Tachyon, huh?
I've been working on the ESP8266 with a friend, he tames dragons. We have an almost complete build with a full file system, graphical file tree display and the ACE javascript editor (supports FORTH and 109 other languages using Textmate, VI, Ace or custom keymap input). We are working to minimize the footprint currently at 456K sans ACE, about another 170K with a couple of language choices. It's all javascript, let the browser do the heavy lifting of syntax highlighting, autocomplete.... This is the kitchen sink with a full implementation of jquery, jquery UI, require.js, backbone and marionette! This is a self hosting Web App development system and portable to any embedded web server, ding ding Tachyon. Peter I might need you or MJB to help with a few of the http server side endpoints once we finalize our system on the ESP8266.
Stay tuned, this thing is really cool and once loaded/cached require.js makes the system super responsive.
I'm thinking about allowing a master on the ping-pong network to read a binary file from SD card and network boot the slave Props. I figure that I could also extend the serial format to 9-bits so that I can send data bytes without encoding. Even at 1Mbps I can send data back to back as there is no need to ping-pong when globally or by group so I could load 32k of hub RAM in less than half a second. To make it more resilient the data would be in packets that have checksums and then the packet repeats one or two times more immediately afterwards so that once a good packet is received and written to hub as it is received byte by byte, then it will ignore any repeat packets (which may have errors). This is nice and simple and there could be a poll at the end of load to check that all the units are right. Maybe the repeat packet stuff could be triggered by a "push-to-talk" pulse from any number of Props that detect a bad packet.
This network boot mode might work out to be simpler than having a protected boot EEPROM loading a binary in from local SD card. But even so it doesn't preclude SD boot and even allows "FTP" both ways over the single wire or RS485 network.
How are you guys handling loading a binary into hub RAM from SD?
The low-level SD routines in FemtoBasic can read a block of data of up to 32K starting from anywhere on the SD card. A flag bit in the control block for the read call sets load mode which checks the 8 bit checksum in the binary file. Other flags cause the calling cog to be stopped prior to loading or the new binary to be executed by the loader's cog after loading (rather than using the calling cog). All of the SD card I/O routines fit in a single cog which waits for control blocks to be posted in a common area. By default a load call is for 32K.
Kye's Fat driver runs out of a cog for loading 32KB. He passes a 64 sector list to the cog that then just reads each sector into the cog.
This is what I use in my Prop OS, except I don't load the top parts.
I replace the clock frequency and xtal parameters (hub $0000-0005) with what I previously saved.
Kye's Fat driver runs out of a cog for loading 32KB. He passes a 64 sector list to the cog that then just reads each sector into the cog.
This is what I use in my Prop OS, except I don't load the top parts.
I replace the clock frequency and xtal parameters (hub $0000-0005) with what I previously saved.
Wow! That's quite cool. So it uses no hub memory at all once you start it?
A loader can't require hub memory because it may be overlaid. Most fetch parameters from a "mailbox", then don't use that area until loading is done (perhaps to return modified parameters). If, as in my case, a Spin interpreter is started, the clock freq and xtal info are saved and restored and the mailbox info is not changed.
A loader can't require hub memory because it may be overlaid. Most fetch parameters from a "mailbox", then don't use that area until loading is done (perhaps to return modified parameters). If, as in my case, a Spin interpreter is started, the clock freq and xtal info are saved and restored and the mailbox info is not changed.
Duh. I wasn't thinking. Of course it uses hub memory. It is *loading* hub memory so hub memory is its buffer.
Comments
And then wanted to try my WS2812 play,
but discovered there is still some functionality not implemented in EXTEND
Like .. ORG, BYTE, #P8, &12.13.14.15 number parsing
I think it makes little sense to rewrite my code - which I could of course -
to work around those missing functions
or extend the EXTEND ;-) - while ORG, BYTE ... probably could easily be moved from EXTEND-V3, number parsing integrates closer to the new kernel.
So I better stay with T3 for now then.
But will closely follow T4 ... thanks Peter
BTW - (byte, word, long) can't take CSVs yet, only a single definition and (bytes, words, longs) in V3 would always long align whereas in V4 words aligns to words and bytes doesn't align. If you don't want any alignment then use DS to create the structure. I will try to update the document but basically I'm not trying to complicate the kernel any more than I need to while I experiment.
Number parsing in V4 is handled at the character input level where it tries to build a number while building a word. If the number of digits = the number of characters then there is no need to check it any further or search the dictionary, it is pushed onto the stack. Whether it is accepted as a digit depends upon the #/$/% prefix or current base if no prefix is used. There is no reason though that I cannot process the "number" further if it is in V3 form with intermixed with symbols.
I will probably implement non-volatile variables but not in the C sense but as variables that are backed up with code in EEPROM whereas most variables are in the reclaimed hub RAM area that is occupied by the kernel and serial cog images in EEPROM and so cannot be backed up there. V3 had data and code mixed which was easy to backup but also took up code memory and if a variable was overrun it certainly caused problems.
EDIT: My character input routine already allowed for digit separators so I assigned a few codes etc. Now you can type #P16 or 10,000 or 10_0000 etc. Also added aliases for byte/word/long etc
Separators are:
I had checked EXTEND ... but only 5 minutes - and this is not enough for all the changes ;-)
I will be catching up.
Unfortunately I have little free time for Tachyon right now.
The project here turns out far bigger than originally planned.
Working on the plans for a 250m³ water tank and a ~ 3 million liter/3000m³ 'lake'.
And you have to control everything here in Spain - even the mixture of the concrete, so they do it right.
With the climate change southern spain is getting even more dry these days.
Province Almeria is at 7% of their storage capacity ... we are a bit better here.
thanks
loaded up T4.spin + latest EXTEND - all fine :-)
then my WS2881B-play.fth
immediately blinks - wow :-)
Findings:
TABLE seems not defined yet - should be easy to add - will check later
"c" single character literals seem to be not implemented as well - will check later
now back to work ...
I noticed that by the time I was compiling EASYNET after EASYFILE and EXTEND that I needed to set the terminal line delay to 40ms. Not being happy with that I experimented with supplementing the dictionary search with LMM, scrubbed that, then a RUNMOD PASM module which was good but interfered with other RUNMODs when interactively testing.
So I squeezed all the required functionality into 21 longs (the maximum RUNMOD size) and now have this loaded automatically during a block mode source code load that starts with the TACHYON keyword and ends with END. Block load mode speeds up compilation by not echoing anything except errors and simply updating the line number prompt. During normal interactive mode it uses the slower but less invasive dictionary search so we get the best of both worlds.
With the fast dictionary search mode I can now set minicom to 3ms line delay at 921600 baud. Most of those lines of code have a lot more than one instruction and having 10 or more instructions on one line is not uncommon which is why it needs time to process all those searches.
Let's see if I can do better later on.
A good compile speed will also help the dynamic loading of code/scripts and eventually the dynamic webserver, when I get back to it.
Having T4 running on the IoT5500+P8 might be a good reason to have a look at it again ...
btw: I discovered (by reading 'documentation' ;-) and trying it out ) -
that with 'a' 'ax works as well
so I was thinking instead of wasting bytes to check for the closing '
maybe to streamline it with the other use of
^a as 'a for single character literal instead of the use of closing '
could work as well ...
and make a cllear distinction from " a" single char string.
Yes, the only checks it needs to make is the first character and the length so a '?' will work just as well as '?? etc but still needs to be 3 characters long. I think 'A' reads better than just 'A as that may be a pointer to some code fragment or something. If it's 3 characters and starts with a ' then it is a character literal or if it starts with a ^ and is 2 characters long then it is a control character literal.
Oh yes the dynamic webserver <?fth ." Hello World MJB" ?> for T4.
@Peter, really neat to see EasyNet "up". Will you still be able to recover that estimated amount of memory now that you have it all loaded and running?
Recovering hub RAM is easy once I implement my hybrid RAM/EEPROM dictionary where the entries in the EEPROM are fixed length entries with a maximum 12 character length suitable for a fast binary search. Despite all the loud noises I heard when I proposed this I am still amused that anyone would be worried about that. With everything loaded including the decompiler etc and with the dictionary still in RAM I ran a simple little dictionary analyzer that tallied up names of the same length, with zero representing the sum total. Have a look- I'm pretty sure that I won't mind choosing a better name and trimming that "one" entry of 13 characters
IF you do as you said before, just copying the words with 12 chars and less to EEPROM and
keeping the others - if there are any - in backed up RAM, then nothing is lost anyhow.
In LISP there is fasl (fast load), where source files are precompiled and can be loded in very fast without parsing the whole thing. If need be, this could be done here as well.
If it is done the simple way, the precompiled code would only load on the image it was created on,
but this would save any linking steps.
For my code I agree totally - I like short as well.
Some time ago when this question about a fixed length came up my argument was
only the gut feeling, that I do not like constraints ;-).
AND since FORTH is so wonderfully extensible it's interpreter can also be used to implement domain/problem specific vocabularies that might be given from outside - and 'could' exceed the 12 char limit.
Just remember how easy it was so implement NEMA? parsing.
Or have a look at how the FTP, Telnet and HTTP clients are implemented.
Luckily FTP uses only short max 6 char commands, that get defined as Tachyon words and
a little fiddling and the FTP handler is born.
Those wunderful options, that we of course do not know the use of today - is what I was talking.
AND when Peter said he will keep the variable length in RAM and move only the <= 12 words to EEPROM,
than I fully supported this - since now we have both benefits.
So we can eat the cake and keep it.
What more can you hope for.
AND if speed and memory really require it, then I am also fine with fixed 12 chars in RAM
IF we get a meaningful error message ;-)
BUT it does not look like it would really save memory.
But it would crash every time although I could add word or long elements without any problems. Turns out that as I add each element which is added in code memory that this created a word alignment problem since the the number is compiled first as is normal for all Tachyon code even in interactive mode, then GRAB'ed by executing. V4 expects all code to be word aligned, even strings etc. If I wanted to allow for byte elements I had to compile it as a word first but flag that I had the high byte free so that the next byte element would simply GRAB and then store it's value in the previous byte location that had already been allocated. If the last byte was an odd element then it would simply waste the high byte of the word. Just thought I'd share that little gotcha.
The & prefix that I use for IP decimal byte notation has been added as well and besides IP style notation such as &192.168.0.150 which is much easier to enter than $C0A8.0096 the & is also useful for compacted I/O pin assignments that I use for SPI, SD cards, WIZnet chips etc. I pack 4 pins into a long usually assigned to a constant so that I can describe a board with a single constant at runtime. For instance I have these 4 constants that define the pins that are used for SD card interfacing for 4 different boards:
At runtime I simply say: Which assigns the chip enable, the SD data out (MISO), the SD data in (MOSI), and the SD clock after which I can initialize the card and mount the FAT32 file system. Easy!
I'm working towards running some projects with V4 and so I'm filling in the blanks and making changes to suit etc and have just ported over my 20x4 character LCD module which is very comprehensive and as all Tachyon devices works transparently as if it were a serial output device responding to control characters and sequences etc in a similar manner to a serial terminal but of course with device specific control codes for big digits, contrast adjustment, back-lighting etc. This module was primarily where I was testing out the TABLE and table building words.
Here's a decompilation of the routine that handles character data, all variable addresses or constants 15-bits and under are compiled directly as a literal:
To kick V4 along I have a project where I need to control two or more commercial A/C units which at present have two separate and fiddly little control panels connected via RS485 up to a relay pcb in the A/C. The relay pcb doesn't really do much as it is a slave but does measure a thermistor in the return air that the existing control panel reads. These control panels are connected via 8-core twisted pair data cable with two pairs doubled up for +12V from the A/C and one pair for RS485 and one spare. Since the relays only really switch optos I plan to do away with the relay pcb and connect those four optos to four wires, one common, two for the thermistor, and one spare direct to my pcb which has a open-drain shift register driving two sets of four relays.
My control panel handles these two units via a 320x240 touch TFT screen with SSD2119 controllers that I happen to have that I interfaced to Tachyon back in the early days and were collecting dust but I have now upgraded all of that for V4. I plan to have additional sensors on RS485 using my ping-pong protocol.
Here's what the screen looks like so far.
Here's a snippet of code which displays the "LEDs".
BTW, V4 can do all this including FAT32 virtual memory and WIZnet servers etc - all in a standard 32k P1.
Now how much code space is left after all the goodies you mentioned include your app?
dp
Practical application is what refines and defines a language or environment, and rather than a language looking for an application, Tachyon has always been driven by applications looking for a means to be implemented. Also engineering is about making things work with what we've got rather than saying if or when, so Tachyon is the "making things work" part of engineering, making "when" today, and "if" is. Benchmarks and popularity aren't much use if it doesn't cut the mustard since the language is there to help get the job done, and the job when done is not about the language. If debates were about how well an application is implemented, then debates about languages would be a moot point. The proof is in the pudding in that the result speaks for itself and is a far greater testament than opinions.
So I'm saying all this because I don't look at how much memory I have left, I just look at how much I can get done. If I need to do more I have options including moving the dictionary to EEPROM, running scripts or loading code modules from EEPROM/Flash/SD etc. We have "a bird in the hand", eight 32-bit CPUs waiting to be used, so why should we go pining for the P2 in the bush? What's worth more?
I had another look at the cleaned-up version of your garden program and immediately saw areas that could be removed or redone even though we refactored the code a lot. Take a look at this: that shouldn't even be a routine, just say:
Then right up above it you set defaults yet this is begging for a table of default values that you just CMOVE rather than hand picking each value.
I think the problem with coding is that it is fair enough you write it first to get it functional but even just a cursory revision of the flow of each routine itself would reveal some detail that can be combined or removed altogether. The other thing is being familiar with some of the built-in functions such as ~ W~ C~ for clearing variables so that rather than writing 0 myvar ! you could write myvar ~ instead. In V3 the first form didn't take up any more memory and was faster but in V4 it is desirable to write it second way,
However in saying all this I don't think your coding style itself would make it a memory hog although I do see lots and lots of messages embedded in the code. Perhaps if I reintroduce the EPRINT function which kept print strings in upper EEPROM then maybe that would help so I will have a look as I know that this might help elsewhere. I just want this function to act transparently so that we don't have to worry about cluttering the code with any settings other than switching it on.
BTW, my previous post was outlining my thinking in regards to Tachyon as I thought that if I go down the path of looking to see "how much memory is left over" then I would be painting myself into a corner as memory left over is memory wasted
we never waste free memory -
we find creative ways of filling it ;-)
and then with just a little more creativity we / you create space again ...
I like this :-)
Most of these apps are using the HSUART for ping-pong RS485 network too. I'd like to see F32 up and running too but I haven't had a real need to interface it properly yet, maybe that's a good job for a fellow Tachyonite?
A typical startup screen
I've been working on the ESP8266 with a friend, he tames dragons. We have an almost complete build with a full file system, graphical file tree display and the ACE javascript editor (supports FORTH and 109 other languages using Textmate, VI, Ace or custom keymap input). We are working to minimize the footprint currently at 456K sans ACE, about another 170K with a couple of language choices. It's all javascript, let the browser do the heavy lifting of syntax highlighting, autocomplete.... This is the kitchen sink with a full implementation of jquery, jquery UI, require.js, backbone and marionette! This is a self hosting Web App development system and portable to any embedded web server, ding ding Tachyon. Peter I might need you or MJB to help with a few of the http server side endpoints once we finalize our system on the ESP8266.
Stay tuned, this thing is really cool and once loaded/cached require.js makes the system super responsive.
This network boot mode might work out to be simpler than having a protected boot EEPROM loading a binary in from local SD card. But even so it doesn't preclude SD boot and even allows "FTP" both ways over the single wire or RS485 network.
How are you guys handling loading a binary into hub RAM from SD?
This is what I use in my Prop OS, except I don't load the top parts.
I replace the clock frequency and xtal parameters (hub $0000-0005) with what I previously saved.