I just grabbed the latest (15 hours old) from Dropbox: Tachyon V2.4 and Extend.fth. I'm using a Propeller BOE on Win7 with TeraTerm 4.78 (all my usual suspects).
I load Tachyon (F11 from source) to the board, start up Tera Term 230,400 (15ms line delay). When I paste EXTEND.fth into TeraTerm, I get this:
[code]
ok
( EXTEND.fth ) ok
ok
TACHYON
Propeller .:.:--TACHYON--:.:. Forth V23140619.0000
ok
0000 ok
0001 ok
0002 ok
0003 okND.fth ." Primary extensions to TACHYON kernel - 121122.1200 " ;
0004 ok
" !!!!!!!!!!!!!!!!!!!!! REQUIRES LATEST KERNEL V2.0 121012.2200 upwards !!!!!!!!0005 ok
0006 ok
0007 ok
0008 ok
0009 ok DUP $0A <> IF $100 OR 2* (EMIT) ELSE DROP THEN ;
0010 ok
\
0011 ok
\
0012 ok
0013 ok 1 flags CLR ' LEMIT uemit W! ;
0014 ok
\
0015 ok
0016 ok 1 flags SET 0 uemit W! ;
0017 ok
0018 @
Same set up here except with an activity board. Load current binary works great, cut and paste the extend get to about line 17 and get a missing word, then about 20 minutes later I get several more then nothing. Let run all afternoon into late evening and it never finished with the log on and prompt. I know its something I am not doing but what?
I used Notepad ++ to copy the file and terra term to paste into Tachyon. Also tried to reduce baud rate and left the delays set to original setting...:blank:
I am as usual confused today. This morning when I rebooted my Act brd the extension file showed up in the start up screen, Peter please ignore my mental issues. I assumed that when the extension completed it would automatic reboot. My bad...
Works just fine on my quickstart, wow V2.4x has some really neat stuff! Thanks Peter
0035 ok
0267 INCLUDING #9 PIN_I/O_OPERATIONS
0436 INCLUDING #8 CHARACTER_OUTPUT
0493 INCLUDING #7 LOCAL_VARIABLES
0515 INCLUDING #6 FIXED_POSITION_VARIABLES
0571 INCLUDING #5 MATHS_FUNCTIONS
0707 INCLUDING #12 NUMBER_PRINT_FORMATING
0822 INCLUDING #19 ANSI_TERMINAL
0998 INCLUDING #24 INTERTASK_COMMUNICATIONS
1027 INCLUDING #20 STRINGS
1102 INCLUDING #21 SAN_FILTER
1128 INCLUDING #22 MCP3208_8_channel_ADC
1407 INCLUDING #13 PBASIC_STYLE_SERIAL_I/O
1441 INCLUDING #14 EXAMINE_SPECIAL_PURPOSE_REGISTERS
1486 INCLUDING #15 Memory Map Reporting
1917 INCLUDING #17 Virtual RTC words 51 48 17 3B
2024 INCLUDING #10 PWM
2084 INCLUDING #11 HEX FILE LOAD & DUMP
2163 INCLUDING #18 COMPILER REPORTING
2270 ok
2271 ok
2272
00:00:00 End of source code, 2273 lines processed and 0000 errors found
MODULES LOADED:
1900: EXTEND.fth Primary extensions to TACHYON kernel - 140905-173O
Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
Clock frequency = 80,000,000
NAMES: $5CB2...7471 for 6079 (3682 bytes added)
CODE: $0000...33CC for 7181 (6860 bytes added)
CALLS: 0452 vectors free
RAM: 10470 bytes free
ok
?BACKUP ok
ok
Somewhat off topic. In searching for some Forth info, I ran across a question on Stack Overflow asking about a multicore forth back in 2011. The question remains open and is largely unanswered in terms of a practical implementation. There seems to be at least 3 on this forum. Care to contribute an answer?
Somewhat off topic. In searching for some Forth info, I ran across a question on Stack Overflow asking about a multicore forth back in 2011. The question remains open and is largely unanswered in terms of a practical implementation. There seems to be at least 3 on this forum. Care to contribute an answer?
Just keeping the reply to this forum but considering the reference it seems to be mainly academic in nature? Computer languages to many are a great source of debate, like Apple vs Android etc etc. Personally I find all the Forth forums very boring as this debate and also about features of the language are bounced back and forth (pun) ad nasuem. I can't say I would use Forth for everything, but for me there is a sweet spot between really low end and high end where Forth shines. But it's not about the language really, it's about productivity which increases in an environment that allows you to test out things interactively AND easily, not like interactive Basic peek and poke in decimal etc, but creating defintiions and structures that allow high level interaction at the bare metal layer at close to assembly speed, or at least fast enough.
There's this joke about what's the differnce between a scientist and an engineer? The engineer gets his hands dirty. Yeah, I like to get into it rather than standing around all day talking about it and many times getting into it just proves that most don't know what they are talking about.
Now back to that other forum and not really answering the question either but I don't really consider Tachyon a multicore Forh either, and I think that distinction for the Prop should go to PropForth as not only does it launch multiple Forth consoles one in each core but it also facilitates multi-chip processing too. However this approach seems to have traded off some of the very advantages of Forth that I at least need, one of which is speed, and also compactness too amongst other things. But each to his own and hopefully we have come to our own decision rather than relying upon popular opinions etc.
From the Tachyon code it looks to me the receive serial get left in COG 0 and the rest of the code goes into COG 1.
If i am write how does one put special drivers and such into other COGs using Tachon?
Forgive me if this is a stupid question, i only come around every so often.
cheers,
rich
there are no stupid questions ... maybe ...
if you look at the end of tachyon 2.4.spin you find this
[COLOR=#000000][FONT=Ubuntu Mono]{ Boot-time Spin startup - launches Tachyon into all the remaining cogs and starts serial receive in this cog = 0 }[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono]PUB Start[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono] rxticks := txticks := clkfreq / baudrate [/FONT][/COLOR][COLOR=#000000][FONT=Ubuntu Mono] [/FONT][/COLOR][COLOR=#000000][FONT=Ubuntu Mono]' Force VM transmit routine to correct baud[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono] coginit(1,@HSSerialRx, @rxbuffers)[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono] repeat 6[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono] [/FONT][/COLOR][COLOR=#000000][FONT=Ubuntu Mono]cognew(@RESET, @IDLE_reset)[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono] coginit(0,@RESET, @TERMINAL_reset)[/FONT][/COLOR]
you see that the serial started is started in COG1 and COG0 is loaded with the Tachyon Terminal.
The other 6 COGs get loaded with the Tachyon kernel as well, but put in IDLE state, waiting for a WORD / function to be loaded.
see: ( COG TASK CONTROL )
and ( INTERTASK COMMUNICATIONS ) in EXTEND.fth for how to start a Tachyon-Task in an other COG
EXTEND also defines a TIMER task, that is started in COG 7
see Timer and Keypoll examples here
you can also write PASM drivers to be loaded in COGS, but this currently requires to put the code in Tachyon.spin
you can also write PASM drivers to be loaded in COGS, but this currently requires to put the code in Tachyon.spin
There are easy ways to load directly into cogs form EEPROM or SD so I will update the files to do this which also includes assembling a PASM source from onboard file to a cog PASM object. Simply specify the file and cog to run when you want to run it during runtime, so you can change it on the fly. One moment it's an FFT, next moment it's handling high level communications etc.
Tachyon 2.4 & latest EXTEND.FTH from Dropbox is working fine now. In this message, I reported issues loading extend - after grabbing a fresh copy of extend.fth from Dropbox, it loaded fine onto a Prop BOE and also onto a QuickStart.
Win7, Tera Term, 230400 with 15ms line delay.
The ws2812 code with the MASK change also works just fine with my ws2811 LEDs.
Well it was a short and fast learning curve, looked at the timing, decided that it may be a bit tight for bytecode alone so I do what I do and create a module as there is room for 19 longs in the Tachyon cog to load in special purpose modules which are called with the RUNMOD instruction.
To run this continually (optional of course) in the background of the console cog (why not) just type:
KEYPOLL LEDS
Or else you can run it from the timer cog with:
TIMER ledtimer ( create a timer variable )
' LEDS ledtimer ALARM ( tell this timer what to do when it counts down to zero)
#20 ledtimer TIMEOUT ( timeout in 20ms but need to insert this code in LEDS really to reload timer)
To fill the array with RED you could try this:
pub RED ( value -- ) rgbsz 1 DO DUP I C! 3 +LOOP DROP ;
If you only wanted it updated when you changed something then add LEDS to the end of that code to do that.
So you could type:
20 % RED
and the red bytes in the array should fill up with a value of 51. Well, it should work and the green and blue are similar but different offset (0 DO or 2 DO)
Actually that would factor to:
pub COLOR ( value offset -- ) rgbsz SWAP DO DUP I C! 3 +LOOP DROP ;
pub RED ( value -- ) 1 COLOR ;
pub GREEN ( value -- ) 0 COLOR ;
pub BLUE ( value -- ) 2 COLOR ;
COLOR crashes the prop! It looks to me like it starts stomping on the registers.
Changing to
pub COLOR ( value offset -- ) rgbleds + rgbsz ADO DUP I C! 3 +LOOP DROP ;
works beautifully!
I've got several projects where these will be outrageously useful, and will be attaching a bit of an update with some more capabilities. We need the ability to change the color on specific pixels, the ability to blank the strip without affecting the data in the array among other functions.
COLOR crashes the prop! It looks to me like it starts stomping on the registers.
Changing to
pub COLOR ( value offset -- ) rgbleds + rgbsz ADO DUP I C! 3 +LOOP DROP ;
works beautifully!
I've got several projects where these will be outrageously useful, and will be attaching a bit of an update with some more capabilities. We need the ability to change the color on specific pixels, the ability to blank the strip without affecting the data in the array among other functions.
I agree with Chameleon, just don't get your above COLOR word Peter. I do think you meant ADO instead of DO and need to adjust the initial address of the array with the proper byte offset before the loop?
I agree with Chameleon, just don't get your above COLOR word Peter. I do think you meant ADO instead of DO and need to adjust the initial address of the array with the proper byte offset before the loop?
Yeah, dumb things like that happen as I didn't get to test it out and "rgbleds" was in the original before I factored it out "quickly"
But good to hear it works because when I get some leds I will be posting some videos of some fancy patterns which I will be able to tune interactively of course.
Yeah, dumb things like that happen as I didn't get to test it out and "rgbleds" was in the original before I factored it out "quickly"
But good to hear it works because when I get some leds I will be posting some videos of some fancy patterns which I will be able to tune interactively of course.
What about using 7 strips and pushing the 5X7 font out for a basic scrolling marque
In keypoll of course while running telnet, http, ftp and sending an email, okay maybe email is running in its own cog since it could block a bit.
What about using 7 strips and pushing the 5X7 font out for a basic scrolling marque
In keypoll of course while running telnet, http, ftp and sending an email, okay maybe email is running in its own cog since it could block a bit.
If you want a controlled timing (like for running text) you might better put the redisplay routine into a timer task running in the timer COG.
Or if need be even in it's own COG. All very easy with Tachyon. and since we have some spare COGs we can use them as well.
COLOR crashes the prop! It looks to me like it starts stomping on the registers.
Changing to
pub COLOR ( value offset -- ) rgbleds + rgbsz ADO DUP I C! 3 +LOOP DROP ;
works beautifully!
I've got several projects where these will be outrageously useful, and will be attaching a bit of an update with some more capabilities. We need the ability to change the color on specific pixels, the ability to blank the strip without affecting the data in the array among other functions.
I've had some good success, but am still fighting some bugs. I'm running into some seemingly random reboots, but wanted to toss out the general idea I had. Being a noob, I'm still trying to understand why one solved bug (creating tempgrn, tempred and tempblu after creating pxldata placed the temp colors within pxldata) actually happened...
( WS2812.fth )
TACHYON
[~
FORGET WS2812.fth
pub WS2812.fth PRINT" WS2812 Intelligent RGB LED driver V1.0 1410221430.0000 " ;
IFNDEF [WS2812] --- use newer name for module in case this had the old name
ALIAS [TXRGB] [WS2812]
}
{ configure for the strip in use }
#P0 MASK == WSTXD --- define our transmit pin
--- three bytes for storing temporary color values, used for writing to/reading from the pixel array
#1 BYTE tempgrn
#1 BYTE tempred
#1 BYTE tempblu
#3 BYTE tempcolors
--- configure the pixel array itself
#32 == pxlcount --- number of LEDS in the array
#96 == pxlbytes --- MUST BE 3x pxcount
#96 BYTE pxldata --- pxlbytes
{ read/write tempcolor array }
{ read colors from tempcolor to stack }
pub GRN@ ( -- value ) tempgrn C@ ;
pub RED@ ( -- value ) tempred C@ ;
pub BLU@ ( -- value ) tempblu C@ ;
{ "additive" color setting...leaves other color bytes unaffected }
pub GRN+ ( value -- ) tempgrn C! ;
pub RED+ ( value -- ) tempred C! ;
pub BLU+ ( value -- ) tempblu C! ;
{ "exclusive" color setting...blanks out (zeroes) the other color bytes }
pub COLOR ( blu red grn -- ) tempgrn C! tempred C! tempblu C! ;
pub BLACK ( -- ) 0 tempgrn C! 0 tempred C! 0 tempblu C! ;
pub MAGENTA ( value -- ) BLACK DUP 0 COLOR ;
pub CYAN ( value -- ) BLACK DUP 2/ SWAP 0 SWAP COLOR ;
pub GRN! ( value -- ) BLACK tempgrn C! ;
pub RED! ( value -- ) BLACK tempred C! ;
pub BLU! ( value -- ) BLACK tempblu C! ;
{ pixel setting }
--- CMOVE (src dest num -- ) --- evaluate for byte savings (PXRD, PXWR, etc)
--- use two vectors, but saves a few bytes
pub PXRD ( src dest -- )
SWAP
pub PXWR ( dest src -- )
C@ SWAP C!
;
;
--- very likely unneeded...(PXCOLORADDR, not PXADDR)
pub PXCOLORADDR ( grb pixelid --- coloraddress ) --- used for each read/write to the pixel data array
pub PXADDR ( pixelid -- grnaddr )
3 * pxldata +
;
+
;
pub PX@ ( pixelid -- ) --- read the color setting for a single pixel to tempcolor
PXADDR DUP
tempgrn PXRD
1+ DUP tempred PXRD
1+ tempblu PXRD
;
pub PX! ( pixelid -- ) --- write tempcolor values to a single pixel
PXADDR DUP
tempgrn PXWR
1+ DUP tempred PXWR
1+ tempblu PXWR
;
--- work in progress...figure out why fails after #28 pixels
--- remove numleds after it works for the entire array
pub PXFILL ( numleds -- ) --- write tempcolor to entire pixel array
--- pxlcount 0 DO --- planned function
0 DO --- remove once it works for all leds, regardless of pixel count
I PX!
LOOP
;
{ communicate with the led strip }
pub LEDCONFIG ( -- ) --- needs to be separated for blankleds..."configure" cog, then send three bytes at a time to strip
WSTXD OUTCLR --- Start a RET to synch the chips
WSTXD 4 COGREG! --- setup the I/O pin for the RUNMOD to use
[WS2812] --- select the WS2812 module for RUNMOD
#10 us --- still need a bit of extra delay for a minimum RET op while txd is low
;
pub LEDS ( -- ) --- Replacement for Peter's LEDS...same code, just split into two words
LEDCONFIG
pxldata pxlbytes RUNMOD --- pass the address of the array and the byte count to the RUNMOD
;
--- Is this an easier task for the kernel addition?
pub BLANKLEDS ( -- ) --- Turns off all LEDS (0G 0R 0B) without affecting the color data in pxldata
--- PLACE HOLDER...Figure out crashes with current code first...I have no idea if the strip timing chokes doing this
{
set tempcolors to $000000...easier way?
LEDCONFIG --- set up cog for sending the data to the strip
pxlcount 0 DO --- do once per pixel
tempcolors 3 RUNMOD --- send the temp data to the strip
LOOP
}
{ debug code }
pub DUMPTEMP ( -- ) --- dumps the contents of tempcolor
CR
CR PRINT" ============================================="
CR PRINT" LED TEMP COLORS (" tempgrn . PRINT" , " tempred . PRINT" , " tempblu . PRINT" , " tempcolors . PRINT" )"
CR
PRINT" GREEN: " tempgrn C@ .
PRINT" RED: " tempred C@ .
PRINT" BLUE: " BLU@ .
PRINT" TEMPCOLORS: " tempcolors @ .
;
pub DUMPB ( -- ) --- 3 byte data element array pretty dumper (thanks, D.P.)
DUMPTEMP
CR
CR PRINT" ============================================="
CR PRINT" LED STORED COLORS "
CR
pxldata pxlbytes --- push this onto the stack: arrayaddr arraysize
CR --- Carrriage return to start
ADO I C@ . "-" EMIT --- fetch each first byte show it
I pxldata - 1+ 3 MOD 0= --- test for third byte
IF PRINT" --" pxldata I - 1+ 3 / . PRINT" (" I 2 - . PRINT" )" CR THEN --- pretty print it
LOOP --- around we go
;
]~
END
#28 PXFILL works without issue, but #29 PXFILL reboots the prop...
I'm continuing to work on this, but if anyone has any thoughts as to why I'm getting the reboots, I'd be happy to hear it.
I've had some good success, but am still fighting some bugs. I'm running into some seemingly random reboots, but wanted to toss out the general idea I had. Being a noob, I'm still trying to understand why one solved bug (creating tempgrn, tempred and tempblu after creating pxldata placed the temp colors within pxldata) actually happened...
( WS2812.fth )
TACHYON
[~
FORGET WS2812.fth
pub WS2812.fth PRINT" WS2812 Intelligent RGB LED driver V1.0 1410221430.0000 " ;
IFNDEF [WS2812] --- use newer name for module in case this had the old name
ALIAS [TXRGB] [WS2812]
}
{ configure for the strip in use }
#P0 MASK == WSTXD --- define our transmit pin
--- three bytes for storing temporary color values, used for writing to/reading from the pixel array
#1 BYTE tempgrn
#1 BYTE tempred
#1 BYTE tempblu
#3 BYTE tempcolors
--- configure the pixel array itself
#32 == pxlcount --- number of LEDS in the array
#96 == pxlbytes --- MUST BE 3x pxcount
#96 BYTE pxldata --- pxlbytes
{ read/write tempcolor array }
{ read colors from tempcolor to stack }
pub GRN@ ( -- value ) tempgrn C@ ;
pub RED@ ( -- value ) tempred C@ ;
pub BLU@ ( -- value ) tempblu C@ ;
{ "additive" color setting...leaves other color bytes unaffected }
pub GRN+ ( value -- ) tempgrn C! ;
pub RED+ ( value -- ) tempred C! ;
pub BLU+ ( value -- ) tempblu C! ;
{ "exclusive" color setting...blanks out (zeroes) the other color bytes }
pub COLOR ( blu red grn -- ) tempgrn C! tempred C! tempblu C! ;
pub BLACK ( -- ) 0 tempgrn C! 0 tempred C! 0 tempblu C! ;
pub MAGENTA ( value -- ) BLACK DUP 0 COLOR ;
pub CYAN ( value -- ) BLACK DUP 2/ SWAP 0 SWAP COLOR ;
pub GRN! ( value -- ) BLACK tempgrn C! ;
pub RED! ( value -- ) BLACK tempred C! ;
pub BLU! ( value -- ) BLACK tempblu C! ;
{ pixel setting }
--- CMOVE (src dest num -- ) --- evaluate for byte savings (PXRD, PXWR, etc)
--- use two vectors, but saves a few bytes
pub PXRD ( src dest -- )
SWAP
pub PXWR ( dest src -- )
C@ SWAP C!
;
;
--- very likely unneeded...(PXCOLORADDR, not PXADDR)
pub PXCOLORADDR ( grb pixelid --- coloraddress ) --- used for each read/write to the pixel data array
pub PXADDR ( pixelid -- grnaddr )
3 * pxldata +
;
+
;
pub PX@ ( pixelid -- ) --- read the color setting for a single pixel to tempcolor
PXADDR DUP
tempgrn PXRD
1+ DUP tempred PXRD
1+ tempblu PXRD
;
pub PX! ( pixelid -- ) --- write tempcolor values to a single pixel
PXADDR DUP
tempgrn PXWR
1+ DUP tempred PXWR
1+ tempblu PXWR
;
--- work in progress...figure out why fails after #28 pixels
--- remove numleds after it works for the entire array
pub PXFILL ( numleds -- ) --- write tempcolor to entire pixel array
--- pxlcount 0 DO --- planned function
0 DO --- remove once it works for all leds, regardless of pixel count
I PX!
LOOP
;
{ communicate with the led strip }
pub LEDCONFIG ( -- ) --- needs to be separated for blankleds..."configure" cog, then send three bytes at a time to strip
WSTXD OUTCLR --- Start a RET to synch the chips
WSTXD 4 COGREG! --- setup the I/O pin for the RUNMOD to use
[WS2812] --- select the WS2812 module for RUNMOD
#10 us --- still need a bit of extra delay for a minimum RET op while txd is low
;
pub LEDS ( -- ) --- Replacement for Peter's LEDS...same code, just split into two words
LEDCONFIG
pxldata pxlbytes RUNMOD --- pass the address of the array and the byte count to the RUNMOD
;
--- Is this an easier task for the kernel addition?
pub BLANKLEDS ( -- ) --- Turns off all LEDS (0G 0R 0B) without affecting the color data in pxldata
--- PLACE HOLDER...Figure out crashes with current code first...I have no idea if the strip timing chokes doing this
{
set tempcolors to $000000...easier way?
LEDCONFIG --- set up cog for sending the data to the strip
pxlcount 0 DO --- do once per pixel
tempcolors 3 RUNMOD --- send the temp data to the strip
LOOP
}
{ debug code }
pub DUMPTEMP ( -- ) --- dumps the contents of tempcolor
CR
CR PRINT" ============================================="
CR PRINT" LED TEMP COLORS (" tempgrn . PRINT" , " tempred . PRINT" , " tempblu . PRINT" , " tempcolors . PRINT" )"
CR
PRINT" GREEN: " tempgrn C@ .
PRINT" RED: " tempred C@ .
PRINT" BLUE: " BLU@ .
PRINT" TEMPCOLORS: " tempcolors @ .
;
pub DUMPB ( -- ) --- 3 byte data element array pretty dumper (thanks, D.P.)
DUMPTEMP
CR
CR PRINT" ============================================="
CR PRINT" LED STORED COLORS "
CR
pxldata pxlbytes --- push this onto the stack: arrayaddr arraysize
CR --- Carrriage return to start
ADO I C@ . "-" EMIT --- fetch each first byte show it
I pxldata - 1+ 3 MOD 0= --- test for third byte
IF PRINT" --" pxldata I - 1+ 3 / . PRINT" (" I 2 - . PRINT" )" CR THEN --- pretty print it
LOOP --- around we go
;
]~
END
#28 PXFILL works without issue, but #29 PXFILL reboots the prop...
I'm continuing to work on this, but if anyone has any thoughts as to why I'm getting the reboots, I'd be happy to hear it.
replace every 1+ with 1 + and if it works Peter can explain
replace every 1+ with 1 + and if it works Peter can explain
Nope...I believe I changed from 1 + to 1+ as a possible solution (straw grab)...tried this recommendation with precisely the same outcome.
I'd like to hear any limitations of 1+ vs 1 +, because I can't see any, and using 1+ rather than 1 + saves one byte per call. While I'm learning, I'd like to ingrain as many byte-efficient strategies as possible, like word nesting and 1+ vs 1 +. Using 1+, I have 9044 bytes free, where 1 + leaves me with 9038 (Tachyon + EXTEND + another module I wrote)
replace every 1+ with 1 + and if it works Peter can explain
Absolutely no difference using 1 + instead of 1+ except that 1+ is a Tachyon opcode and only takes 400ns to execute.
4 LAP 1 + LAP .LAP 2. 200us ok
. 5 ok
4 LAP 1+ LAP .LAP 400ns ok
. 5 ok
But here's your problem, look at this code and also your original and besides using defined constants as parameters for other constants, notice BYTE vs BYTES (doh!)
#32 == pxlcount --- number of LEDS in the array
pxlcount 3 * == pxlbytes
pxlbytes [B]BYTES[/B] pxldata --- pxlbytes
vs the original:
--- configure the pixel array itself
#32 == pxlcount --- number of LEDS in the array
#96 == pxlbytes --- MUST BE 3x pxcount
#96 BYTE pxldata --- pxlbytes
pxlcount should also really be ledcount as each led has 3 pixels.
EDIT: looking at the other BYTE defs they might need to be changed too as BYTE will only create byte sized variables without requiring any extra parameters and BYTES needs to know how many bytes in an array as such:
BYTE onebyte
BYTE x,y,z
8 BYTES mybuf
So the purality of BYTE(S) WORD(S) LONG(S) indicates that you need to tell it how many. There are no error messages if you say 20 BYTE as 20 is just another stack parameter that may have a purpose only you know of but as you know Forth does not enforce syntax "you must do it this way" which while fine for students with training wheels is IMO too restictive if you know what you are doing.
BTW, if you mostly deal with decimal numbers you can just change your base to DECIMAL and skip the # tags. Perhaps I may just make decimal the default as I find that I normally prefix all my hex numbers with $ anyway.
Absolutely no difference using 1 + instead of 1+ except that 1+ is a Tachyon opcode and only takes 400ns to execute.
4 LAP 1 + LAP .LAP 2. 200us ok
. 5 ok
4 LAP 1+ LAP .LAP 400ns ok
. 5 ok
.
.
.
Yep the version I wrote worked and I missed the BYTE/S mixup, thus just throwing hay into the wind with wild hope. Thanks for the explanation/s, always.
Absolutely no difference using 1 + instead of 1+ except that 1+ is a Tachyon opcode and only takes 400ns to execute.
4 LAP 1 + LAP .LAP 2. 200us ok
. 5 ok
4 LAP 1+ LAP .LAP 400ns ok
. 5 ok
...AND that it only requires one byte in the code as opposed to two bytes (my original reason for trying it, to start as byte-efficient as possible as early as possible)
But here's your problem, look at this code and also your original and besides using defined constants as parameters for other constants, notice BYTE vs BYTES (doh!)
#32 == pxlcount --- number of LEDS in the array
pxlcount 3 * == pxlbytes
pxlbytes [B]BYTES[/B] pxldata --- pxlbytes
vs the original:
--- configure the pixel array itself
#32 == pxlcount --- number of LEDS in the array
#96 == pxlbytes --- MUST BE 3x pxcount
#96 BYTE pxldata --- pxlbytes
Doh! is right. The simple stuff can kill...can you tell me why it worked well for the first 28 LEDs, but not 29 plus?
I started calculating the byte count, but crashed because I started manipulating the array only (no attention to calling [WS2812]), and pxlcount 3 * BYTES pxldata failed (or something else at the same time during development)...I started with the right intent, just missed a step.
pxlcount should also really be ledcount as each led has 3 pixels.
EDIT: looking at the other BYTE defs they might need to be changed too as BYTE will only create byte sized variables without requiring any extra parameters and BYTES needs to know how many bytes in an array as such:
BYTE onebyte
BYTE x,y,z
8 BYTES mybuf
So the purality of BYTE(S) WORD(S) LONG(S) indicates that you need to tell it how many. There are no error messages if you say 20 BYTE as 20 is just another stack parameter that may have a purpose only you know of but as you know Forth does not enforce syntax "you must do it this way" which while fine for students with training wheels is IMO too restictive if you know what you are doing.
BTW, if you mostly deal with decimal numbers you can just change your base to DECIMAL and skip the # tags. Perhaps I may just make decimal the default as I find that I normally prefix all my hex numbers with $ anyway.
pxlcount vs. ledcount is (human) semantics. I chose pixels since the WS2812s I bought from Adafruit are "Neopixels."
What are your thoughts about adding an led clear to the kernel like the runmod? I see this being essential in a lot of applications, where we'll want to turn off all LEDS without affecting the color data already in the array (such as flashing a pattern on and off). I'm worried that we'll run into timing issues, where the strip will see my approach as an intentional reset...I haven't tested it yet since I've just seen your helpful smack on the forehead for a braindead flub.
While I'm at it, does anyone else have suggestions for additional functions? I'm kinda enjoying this, and this makes a good post "Hello World" project. I've already been thinking about scrolling marquees, so will be looking into multi-strip support.
...AND that it only requires one byte in the code as opposed to two bytes (my original reason for trying it, to start as byte-efficient as possible as early as possible)
Doh! is right. The simple stuff can kill...can you tell me why it worked well for the first 28 LEDs, but not 29 plus?
I started calculating the byte count, but crashed because I started manipulating the array only (no attention to calling [WS2812]), and pxlcount 3 * BYTES pxldata failed (or something else at the same time during development)...I started with the right intent, just missed a step.
pxlcount vs. ledcount is (human) semantics. I chose pixels since the WS2812s I bought from Adafruit are "Neopixels."
What are your thoughts about adding an led clear to the kernel like the runmod? I see this being essential in a lot of applications, where we'll want to turn off all LEDS without affecting the color data already in the array (such as flashing a pattern on and off). I'm worried that we'll run into timing issues, where the strip will see my approach as an intentional reset...I haven't tested it yet since I've just seen your helpful smack on the forehead for a braindead flub.
While I'm at it, does anyone else have suggestions for additional functions? I'm kinda enjoying this, and this makes a good post "Hello World" project. I've already been thinking about scrolling marquees, so will be looking into multi-strip support.
Since the RUNMOD function only requires the start address and count it is easy enough to have a blank area or any other area for that matter such as the tables in ROM but otherwise just feel free to use the BUFFERS area or part thereof.
Initially you could: BUFFERS $800 ERASE BUFFERS pxlbytes + pxlbytes $FF FILL
To blank all the LEDs: BUFFERS pxlbytes RUNMOD
To light em up: BUFFERS pxlbytes + pxlbytes RUNMOD
In fact rather than calling RUNMOD directly you should really have this:
pub SHOW ( address -- ) pxlbytes RUNMOD #50 us ;
So BLANK becomes pub BLANK BUFFERS SHOW ;
Anyway there are all kinds of optimizations possible although I normally worry about "functionality first, features second". The scrolling marquee was one I was going to demo as soon as I get some LEDs but don't let me stop you, keep up the fun work.
EDIT: the crash is simply because you are using a byte array in code space, not normally a problem but it was overwriting the GRN@ to BLU+ words which weren't noticed until it overran COLOR.
pxldata $80 DUMP
0000_3557: 00 C0 1F 62 0F BF 1F 62 0F C0 20 62 0F C0 1F 6A ...b...b.. b...j
0000_3567: 0F BF 1F 6A 0F C0 20 6A 0F C0 1F 6A BF 1F 6A C0 ...j.. j...j..j.
0000_3577: 20 6A 0F 87 C0 1F 6A 87 BF 1F 6A 87 C0 20 6A 0F j....j...j.. j.
0000_3587: C0 26 17 87 BF 25 0F C0 26 17 4A 21 87 21 BF 25 .&...%..&.J!.!.%
0000_3597: 0F C0 26 C0 1F 6A 0F C0 26 BF 1F 6A 0F C0 26 C0 ..&..j..&..j..&.
0000_35A7: 20 6A 0F 21 62 21 6A 0F 0F 85 F5 14 C0 22 29 0F j.!b!j......").
0000_35B7: 0F C0 2A 17 C0 1F C0 29 2C 17 BF 1F C0 29 2C C0 ..*....),....),.
0000_35C7: 20 C0 29 0F C0 2A 17 C0 1F BF 29 2C 17 BF 1F BF .)..*....),.... ok
' COLOR . 3570 ok
' GRN+ . 3564 ok
pxldata #29 + . 3574 ok
You can also define storage areas as constants with ORG such as:
BUFFERS ORG
pxlbytes DS pxldata
1 DS tempgrn
and so on to keep it all together without worrying about slamming into code.
Since the RUNMOD function only requires the start address and count it is easy enough to have a blank area or any other area for that matter such as the tables in ROM but otherwise just feel free to use the BUFFERS area or part thereof.
Initially you could: BUFFERS $800 ERASE BUFFERS pxlbytes + pxlbytes $FF FILL
To blank all the LEDs: BUFFERS pxlbytes RUNMOD
To light em up: BUFFERS pxlbytes + pxlbytes RUNMOD
In fact rather than calling RUNMOD directly you should really have this:
pub SHOW ( address -- ) pxlbytes RUNMOD #50 us ;
So BLANK becomes pub BLANK BUFFERS SHOW ;
Anyway there are all kinds of optimizations possible although I normally worry about "functionality first, features second". The scrolling marquee was one I was going to demo as soon as I get some LEDs but don't let me stop you, keep up the fun work.
Awesome! Once again, I'm thinking about added code, and it was already there...seems to be a recurring theme for me...so many paradigms to overcome, but fun to try. I always keep features in mind, since I need them in order to know when it is functional.
EDIT: the crash is simply because you are using a byte array in code space, not normally a problem but it was overwriting the GRN@ to BLU+ words which weren't noticed until it overran COLOR.
pxldata $80 DUMP
0000_3557: 00 C0 1F 62 0F BF 1F 62 0F C0 20 62 0F C0 1F 6A ...b...b.. b...j
0000_3567: 0F BF 1F 6A 0F C0 20 6A 0F C0 1F 6A BF 1F 6A C0 ...j.. j...j..j.
0000_3577: 20 6A 0F 87 C0 1F 6A 87 BF 1F 6A 87 C0 20 6A 0F j....j...j.. j.
0000_3587: C0 26 17 87 BF 25 0F C0 26 17 4A 21 87 21 BF 25 .&...%..&.J!.!.%
0000_3597: 0F C0 26 C0 1F 6A 0F C0 26 BF 1F 6A 0F C0 26 C0 ..&..j..&..j..&.
0000_35A7: 20 6A 0F 21 62 21 6A 0F 0F 85 F5 14 C0 22 29 0F j.!b!j......").
0000_35B7: 0F C0 2A 17 C0 1F C0 29 2C 17 BF 1F C0 29 2C C0 ..*....),....),.
0000_35C7: 20 C0 29 0F C0 2A 17 C0 1F BF 29 2C 17 BF 1F BF .)..*....),.... ok
' COLOR . 3570 ok
' GRN+ . 3564 ok
pxldata #29 + . 3574 ok
You can also define storage areas as constants with ORG such as:
BUFFERS ORG
pxlbytes DS pxldata
1 DS tempgrn
and so on to keep it all together without worrying about slamming into code.
I ran into precisely the same issue on a different section of the project I'm working on...That's why I had DUMPTEMP and DUMPB spit out the relevant addresses. I was blind, since I looked for precisely that and looked right over it. The noob is humbled. I just haven't had the time to fully understand ORG and the pros and cons (if there are any), but definately see an advantage.
It now works even better than I hoped. I was expecting it to have more of a delay than it actually had, which is always a good thing when you're looking for as fast as friggin' possible. I'm adding some features, and will re-post the whole (functional and with the features I need) module.
When I grow up, I wanna be like Peter. Most coders tell MCUs what to do. He convinces them that they want to do what he wants them to do.
Awesome! Once again, I'm thinking about added code, and it was already there...seems to be a recurring theme for me...so many paradigms to overcome, but fun to try. I always keep features in mind, since I need them in order to know when it is functional.
I ran into precisely the same issue on a different section of the project I'm working on...That's why I had DUMPTEMP and DUMPB spit out the relevant addresses. I was blind, since I looked for precisely that and looked right over it. The noob is humbled. I just haven't had the time to fully understand ORG and the pros and cons (if there are any), but definately see an advantage.
It now works even better than I hoped. I was expecting it to have more of a delay than it actually had, which is always a good thing when you're looking for as fast as friggin' possible. I'm adding some features, and will re-post the whole (functional and with the features I need) module.
When I grow up, I wanna be like Peter. Most coders tell MCUs what to do. He convinces them that they want to do what he wants them to do.
ORG just sets a pointer somewhere into memory that you would like to use for pure storage as opposed to variables which all feature at least a bytecode to say that the following memory is a variable or a constant etc. So when you use ORG you can then use DS (Data Storage) to specify how many bytes you would like at the current storage address and the symbol for it. Unlike an assembler that this concept is taken from the symbol lives on in the Forth dictionary as a constant that supplies the address of that storage area which could be used for anything at all, totally untyped and unchecked.
So for instance we set up some buffers for these LEDs we go like this:
[FONT=courier new]32 == ledcnt
ledcnt 3 * == pxlbytes
BUFFERS ORG --- use BUFFERS for data storage
pxlbytes DS pxldata --- pxldata begins at BUFFERS and ORG is advanced to BUFFERS+96
1 DS tempgrn --- tempgrn becomes a constant set as BUFFERS+96 and ORG is incremented
1 DS tempred
1 DS tempblu
3 DS tempcolors[/FONT]
What's different about this compared to using variables although they both return an address to a storage area is that there are no code bytes mixed in as the code is in code space as a constant whose value is the address of this storage area over here. So you can wipe the whole memory in this data storage area for instance and it won't affect the code but write a long to a byte variable will cause it to zap the code that follows that byte. How we use this DS then is sometimes to keep all our data in one place to allow it to be accessed as a structure such as file system tables and entries etc which are comprised of variable sized records. Have a look at SDCARD.fth and EASYFILE.fth for example.
Now having grown up I wouldn't call myself a coder or perhaps even a programmer plus I've made too many mistakes around too many talented people such as we have on this forum to ever worry about getting a big head and thinking I can get stuff to do what I want it to do, mostly I just coax it along and get lucky sometimes. The thing is with this stuff, more important than important is having fun and learning and sharing. That's something any of us can do and who gets tired of having fun?
With a full filesystem and networking loaded (+app) this 32K RAM bottleneck has been bothering me for ages and the logical thing to do is to move the dictionary to external memory but EEPROM is way too slow and SD seems to be the choice, but how to actually manage and search it efficiently then? A dictionary can grow to 10K and even with SD it takes around 3ms per sector so that 60ms is still way too long to search for each word if we are compiling. So I have looked at hashing schemes and hybrid hashing schemes but they also introduce complexities without saving that much RAM.
Now, finally now I have come up with a scheme which keeps the dictionary in SDFS but can find any word from the console within 3ms, the time it takes to read a sector. This means that I "sacrifice" 2MB of SD but of course that's nothing as I convert 5 bits of the count and 7-bits of the first character as a 1 of 4,096 sector index into a dictionary file. So the sector gets read into a fixed buffer (there are 4 of them for 4 open files) and Tachyon just searches that RAM the same as it would when all the dictionary was in RAM, but now only the possible matches are presented, the ones with the same string length and same first character. Everything from there on works the same.
When a new word is created it goes into the "current" dictionary except of course there's that little step that makes sure it has read in the matching sector. Then the sector gets written and everything continues as normal. From Tachyon's text interpreter point of view the dictionary is a tiny 512 byte sector buffer, except that buffer gets magically loaded and saved as needed.
A dictionary can be converted to SDFS once the SDFS is in place as I am adding a simple SDWORDS which writes all the dictionary to the WORDS.DCT file, reclaims RAM, and then wires itself in to handle the SDFS as necessary.
I needed this has my application that sits on top of all the network layer needed around >2K and I was constantly running out of room. Expect to see a lot more added functionality now and even VGA with a full blown system too.
The slight problem now is that a full system image is comprised of 32K Prop EEPROM, + optional print strings in upper EEPROM + the 2MB WORDS.DCT file to make it complete. So don't expect the Spin tool to load it all with just a 32K binary although it may be that simple plus copy the WORDS.DCT to your SD card.
With a full filesystem and networking loaded (+app) this 32K RAM bottleneck has been bothering me for ages and the logical thing to do is to move the dictionary to external memory but EEPROM is way too slow and SD seems to be the choice, but how to actually manage and search it efficiently then? A dictionary can grow to 10K and even with SD it takes around 3ms per sector so that 60ms is still way too long to search for each word if we are compiling. So I have looked at hashing schemes and hybrid hashing schemes but they also introduce complexities without saving that much RAM.
Now, finally now I have come up with a scheme which keeps the dictionary in SDFS but can find any word from the console within 3ms, the time it takes to read a sector. This means that I "sacrifice" 2MB of SD but of course that's nothing as I convert 5 bits of the count and 7-bits of the first character as a 1 of 4,096 sector index into a dictionary file. So the sector gets read into a fixed buffer (there are 4 of them for 4 open files) and Tachyon just searches that RAM the same as it would when all the dictionary was in RAM, but now only the possible matches are presented, the ones with the same string length and same first character. Everything from there on works the same.
When a new word is created it goes into the "current" dictionary except of course there's that little step that makes sure it has read in the matching sector. Then the sector gets written and everything continues as normal. From Tachyon's text interpreter point of view the dictionary is a tiny 512 byte sector buffer, except that buffer gets magically loaded and saved as needed.
A dictionary can be converted to SDFS once the SDFS is in place as I am adding a simple SDWORDS which writes all the dictionary to the WORDS.DCT file, reclaims RAM, and then wires itself in to handle the SDFS as necessary.
I needed this has my application that sits on top of all the network layer needed around >2K and I was constantly running out of room. Expect to see a lot more added functionality now and even VGA with a full blown system too.
The slight problem now is that a full system image is comprised of 32K Prop EEPROM, + optional print strings in upper EEPROM + the 2MB WORDS.DCT file to make it complete. So don't expect the Spin tool to load it all with just a 32K binary although it may be that simple plus copy the WORDS.DCT to your SD card.
Great news!!! I've been running into the dreading "dictionary is full" error after loading all the networking goodies and wondering what I need/can chop out. Look forward to testing this new functionality when ready.
Comments
I broke my Tachyon!
I just grabbed the latest (15 hours old) from Dropbox: Tachyon V2.4 and Extend.fth. I'm using a Propeller BOE on Win7 with TeraTerm 4.78 (all my usual suspects).
I load Tachyon (F11 from source) to the board, start up Tera Term 230,400 (15ms line delay). When I paste EXTEND.fth into TeraTerm, I get this:
[code]
ok
( EXTEND.fth ) ok
ok
TACHYON
Propeller .:.:--TACHYON--:.:. Forth V23140619.0000
ok
0000 ok
0001 ok
0002 ok
0003 okND.fth ." Primary extensions to TACHYON kernel - 121122.1200 " ;
0004 ok
" !!!!!!!!!!!!!!!!!!!!! REQUIRES LATEST KERNEL V2.0 121012.2200 upwards !!!!!!!!0005 ok
0006 ok
0007 ok
0008 ok
0009 ok DUP $0A <> IF $100 OR 2* (EMIT) ELSE DROP THEN ;
0010 ok
\
0011 ok
\
0012 ok
0013 ok 1 flags CLR ' LEMIT uemit W! ;
0014 ok
\
0015 ok
0016 ok 1 flags SET 0 uemit W! ;
0017 ok
0018 @
I used Notepad ++ to copy the file and terra term to paste into Tachyon. Also tried to reduce baud rate and left the delays set to original setting...:blank:
I'll try it on a Quickstart to rule out a board issue.
OSX, minicom, here's my alias to start minicom for this quickstart board
I use 13 ms line delay no character delay
Somewhat off topic. In searching for some Forth info, I ran across a question on Stack Overflow asking about a multicore forth back in 2011. The question remains open and is largely unanswered in terms of a practical implementation. There seems to be at least 3 on this forum. Care to contribute an answer?
http://stackoverflow.com/questions/5618297/multicore-forth-is-there-one
Rick
Just keeping the reply to this forum but considering the reference it seems to be mainly academic in nature? Computer languages to many are a great source of debate, like Apple vs Android etc etc. Personally I find all the Forth forums very boring as this debate and also about features of the language are bounced back and forth (pun) ad nasuem. I can't say I would use Forth for everything, but for me there is a sweet spot between really low end and high end where Forth shines. But it's not about the language really, it's about productivity which increases in an environment that allows you to test out things interactively AND easily, not like interactive Basic peek and poke in decimal etc, but creating defintiions and structures that allow high level interaction at the bare metal layer at close to assembly speed, or at least fast enough.
There's this joke about what's the differnce between a scientist and an engineer? The engineer gets his hands dirty. Yeah, I like to get into it rather than standing around all day talking about it and many times getting into it just proves that most don't know what they are talking about.
Now back to that other forum and not really answering the question either but I don't really consider Tachyon a multicore Forh either, and I think that distinction for the Prop should go to PropForth as not only does it launch multiple Forth consoles one in each core but it also facilitates multi-chip processing too. However this approach seems to have traded off some of the very advantages of Forth that I at least need, one of which is speed, and also compactness too amongst other things. But each to his own and hopefully we have come to our own decision rather than relying upon popular opinions etc.
From the Tachyon code it looks to me the receive serial get left in COG 0 and the rest of the code goes into COG 1.
If i am write how does one put special drivers and such into other COGs using Tachon?
Forgive me if this is a stupid question, i only come around every so often.
cheers,
rich
if you look at the end of tachyon 2.4.spin you find this you see that the serial started is started in COG1 and COG0 is loaded with the Tachyon Terminal.
The other 6 COGs get loaded with the Tachyon kernel as well, but put in IDLE state, waiting for a WORD / function to be loaded.
see:
( COG TASK CONTROL )
and
( INTERTASK COMMUNICATIONS ) in EXTEND.fth for how to start a Tachyon-Task in an other COG
EXTEND also defines a TIMER task, that is started in COG 7
see Timer and Keypoll examples here
you can also write PASM drivers to be loaded in COGS, but this currently requires to put the code in Tachyon.spin
There are easy ways to load directly into cogs form EEPROM or SD so I will update the files to do this which also includes assembling a PASM source from onboard file to a cog PASM object. Simply specify the file and cog to run when you want to run it during runtime, so you can change it on the fly. One moment it's an FFT, next moment it's handling high level communications etc.
rich
Win7, Tera Term, 230400 with 15ms line delay.
The ws2812 code with the MASK change also works just fine with my ws2811 LEDs.
Fun stuff!!
COLOR crashes the prop! It looks to me like it starts stomping on the registers.
Changing to works beautifully!
I've got several projects where these will be outrageously useful, and will be attaching a bit of an update with some more capabilities. We need the ability to change the color on specific pixels, the ability to blank the strip without affecting the data in the array among other functions.
I agree with Chameleon, just don't get your above COLOR word Peter. I do think you meant ADO instead of DO and need to adjust the initial address of the array with the proper byte offset before the loop?
Yeah, dumb things like that happen as I didn't get to test it out and "rgbleds" was in the original before I factored it out "quickly"
But good to hear it works because when I get some leds I will be posting some videos of some fancy patterns which I will be able to tune interactively of course.
What about using 7 strips and pushing the 5X7 font out for a basic scrolling marque
In keypoll of course while running telnet, http, ftp and sending an email, okay maybe email is running in its own cog since it could block a bit.
Or if need be even in it's own COG. All very easy with Tachyon. and since we have some spare COGs we can use them as well.
I've had some good success, but am still fighting some bugs. I'm running into some seemingly random reboots, but wanted to toss out the general idea I had. Being a noob, I'm still trying to understand why one solved bug (creating tempgrn, tempred and tempblu after creating pxldata placed the temp colors within pxldata) actually happened...
#28 PXFILL works without issue, but #29 PXFILL reboots the prop...
I'm continuing to work on this, but if anyone has any thoughts as to why I'm getting the reboots, I'd be happy to hear it.
replace every 1+ with 1 + and if it works Peter can explain
Nope...I believe I changed from 1 + to 1+ as a possible solution (straw grab)...tried this recommendation with precisely the same outcome.
I'd like to hear any limitations of 1+ vs 1 +, because I can't see any, and using 1+ rather than 1 + saves one byte per call. While I'm learning, I'd like to ingrain as many byte-efficient strategies as possible, like word nesting and 1+ vs 1 +. Using 1+, I have 9044 bytes free, where 1 + leaves me with 9038 (Tachyon + EXTEND + another module I wrote)
I'll move Forth and (hopefully) succeed!
Absolutely no difference using 1 + instead of 1+ except that 1+ is a Tachyon opcode and only takes 400ns to execute.
But here's your problem, look at this code and also your original and besides using defined constants as parameters for other constants, notice BYTE vs BYTES (doh!)
vs the original:
pxlcount should also really be ledcount as each led has 3 pixels.
EDIT: looking at the other BYTE defs they might need to be changed too as BYTE will only create byte sized variables without requiring any extra parameters and BYTES needs to know how many bytes in an array as such:
BYTE onebyte
BYTE x,y,z
8 BYTES mybuf
So the purality of BYTE(S) WORD(S) LONG(S) indicates that you need to tell it how many. There are no error messages if you say 20 BYTE as 20 is just another stack parameter that may have a purpose only you know of but as you know Forth does not enforce syntax "you must do it this way" which while fine for students with training wheels is IMO too restictive if you know what you are doing.
BTW, if you mostly deal with decimal numbers you can just change your base to DECIMAL and skip the # tags. Perhaps I may just make decimal the default as I find that I normally prefix all my hex numbers with $ anyway.
Doh! is right. The simple stuff can kill...can you tell me why it worked well for the first 28 LEDs, but not 29 plus?
I started calculating the byte count, but crashed because I started manipulating the array only (no attention to calling [WS2812]), and pxlcount 3 * BYTES pxldata failed (or something else at the same time during development)...I started with the right intent, just missed a step.
pxlcount vs. ledcount is (human) semantics. I chose pixels since the WS2812s I bought from Adafruit are "Neopixels."
What are your thoughts about adding an led clear to the kernel like the runmod? I see this being essential in a lot of applications, where we'll want to turn off all LEDS without affecting the color data already in the array (such as flashing a pattern on and off). I'm worried that we'll run into timing issues, where the strip will see my approach as an intentional reset...I haven't tested it yet since I've just seen your helpful smack on the forehead for a braindead flub.
While I'm at it, does anyone else have suggestions for additional functions? I'm kinda enjoying this, and this makes a good post "Hello World" project. I've already been thinking about scrolling marquees, so will be looking into multi-strip support.
Since the RUNMOD function only requires the start address and count it is easy enough to have a blank area or any other area for that matter such as the tables in ROM but otherwise just feel free to use the BUFFERS area or part thereof.
Initially you could: BUFFERS $800 ERASE BUFFERS pxlbytes + pxlbytes $FF FILL
To blank all the LEDs: BUFFERS pxlbytes RUNMOD
To light em up: BUFFERS pxlbytes + pxlbytes RUNMOD
In fact rather than calling RUNMOD directly you should really have this:
pub SHOW ( address -- ) pxlbytes RUNMOD #50 us ;
So BLANK becomes pub BLANK BUFFERS SHOW ;
Anyway there are all kinds of optimizations possible although I normally worry about "functionality first, features second". The scrolling marquee was one I was going to demo as soon as I get some LEDs but don't let me stop you, keep up the fun work.
EDIT: the crash is simply because you are using a byte array in code space, not normally a problem but it was overwriting the GRN@ to BLU+ words which weren't noticed until it overran COLOR.
pxldata $80 DUMP
0000_3557: 00 C0 1F 62 0F BF 1F 62 0F C0 20 62 0F C0 1F 6A ...b...b.. b...j
0000_3567: 0F BF 1F 6A 0F C0 20 6A 0F C0 1F 6A BF 1F 6A C0 ...j.. j...j..j.
0000_3577: 20 6A 0F 87 C0 1F 6A 87 BF 1F 6A 87 C0 20 6A 0F j....j...j.. j.
0000_3587: C0 26 17 87 BF 25 0F C0 26 17 4A 21 87 21 BF 25 .&...%..&.J!.!.%
0000_3597: 0F C0 26 C0 1F 6A 0F C0 26 BF 1F 6A 0F C0 26 C0 ..&..j..&..j..&.
0000_35A7: 20 6A 0F 21 62 21 6A 0F 0F 85 F5 14 C0 22 29 0F j.!b!j......").
0000_35B7: 0F C0 2A 17 C0 1F C0 29 2C 17 BF 1F C0 29 2C C0 ..*....),....),.
0000_35C7: 20 C0 29 0F C0 2A 17 C0 1F BF 29 2C 17 BF 1F BF .)..*....),.... ok
' COLOR . 3570 ok
' GRN+ . 3564 ok
pxldata #29 + . 3574 ok
You can also define storage areas as constants with ORG such as:
BUFFERS ORG
pxlbytes DS pxldata
1 DS tempgrn
and so on to keep it all together without worrying about slamming into code.
I ran into precisely the same issue on a different section of the project I'm working on...That's why I had DUMPTEMP and DUMPB spit out the relevant addresses. I was blind, since I looked for precisely that and looked right over it. The noob is humbled. I just haven't had the time to fully understand ORG and the pros and cons (if there are any), but definately see an advantage.
It now works even better than I hoped. I was expecting it to have more of a delay than it actually had, which is always a good thing when you're looking for as fast as friggin' possible. I'm adding some features, and will re-post the whole (functional and with the features I need) module.
When I grow up, I wanna be like Peter. Most coders tell MCUs what to do. He convinces them that they want to do what he wants them to do.
ORG just sets a pointer somewhere into memory that you would like to use for pure storage as opposed to variables which all feature at least a bytecode to say that the following memory is a variable or a constant etc. So when you use ORG you can then use DS (Data Storage) to specify how many bytes you would like at the current storage address and the symbol for it. Unlike an assembler that this concept is taken from the symbol lives on in the Forth dictionary as a constant that supplies the address of that storage area which could be used for anything at all, totally untyped and unchecked.
So for instance we set up some buffers for these LEDs we go like this:
What's different about this compared to using variables although they both return an address to a storage area is that there are no code bytes mixed in as the code is in code space as a constant whose value is the address of this storage area over here. So you can wipe the whole memory in this data storage area for instance and it won't affect the code but write a long to a byte variable will cause it to zap the code that follows that byte. How we use this DS then is sometimes to keep all our data in one place to allow it to be accessed as a structure such as file system tables and entries etc which are comprised of variable sized records. Have a look at SDCARD.fth and EASYFILE.fth for example.
Now having grown up I wouldn't call myself a coder or perhaps even a programmer plus I've made too many mistakes around too many talented people such as we have on this forum to ever worry about getting a big head and thinking I can get stuff to do what I want it to do, mostly I just coax it along and get lucky sometimes. The thing is with this stuff, more important than important is having fun and learning and sharing. That's something any of us can do and who gets tired of having fun?
Now, finally now I have come up with a scheme which keeps the dictionary in SDFS but can find any word from the console within 3ms, the time it takes to read a sector. This means that I "sacrifice" 2MB of SD but of course that's nothing as I convert 5 bits of the count and 7-bits of the first character as a 1 of 4,096 sector index into a dictionary file. So the sector gets read into a fixed buffer (there are 4 of them for 4 open files) and Tachyon just searches that RAM the same as it would when all the dictionary was in RAM, but now only the possible matches are presented, the ones with the same string length and same first character. Everything from there on works the same.
When a new word is created it goes into the "current" dictionary except of course there's that little step that makes sure it has read in the matching sector. Then the sector gets written and everything continues as normal. From Tachyon's text interpreter point of view the dictionary is a tiny 512 byte sector buffer, except that buffer gets magically loaded and saved as needed.
A dictionary can be converted to SDFS once the SDFS is in place as I am adding a simple SDWORDS which writes all the dictionary to the WORDS.DCT file, reclaims RAM, and then wires itself in to handle the SDFS as necessary.
I needed this has my application that sits on top of all the network layer needed around >2K and I was constantly running out of room. Expect to see a lot more added functionality now and even VGA with a full blown system too.
The slight problem now is that a full system image is comprised of 32K Prop EEPROM, + optional print strings in upper EEPROM + the 2MB WORDS.DCT file to make it complete. So don't expect the Spin tool to load it all with just a 32K binary although it may be that simple plus copy the WORDS.DCT to your SD card.
Great news!!! I've been running into the dreading "dictionary is full" error after loading all the networking goodies and wondering what I need/can chop out. Look forward to testing this new functionality when ready.