In attempting to understand some of the words in Tachyon I have opened Tachyon V2.3.spin and the extension files looking for clues. When I do I often get a warning "Not all unicode characters could be converted to ASCII". My favorite editor is The Semware Editor - known as QEdit with I first started using it. I have also noticed some characters that the editor displays as upper 128 code ASCII. I have also looked at the file in WordPad and seen those upper characters. Am I endangering the contents of those files if I have to save, for instance if I must customize a parameter? What would be a better editor to use? I luv my TSE.
In attempting to understand some of the words in Tachyon I have opened Tachyon V2.3.spin and the extension files looking for clues. When I do I often get a warning "Not all unicode characters could be converted to ASCII". My favorite editor is The Semware Editor - known as QEdit with I first started using it. I have also noticed some characters that the editor displays as upper 128 code ASCII. I have also looked at the file in WordPad and seen those upper characters. Am I endangering the contents of those files if I have to save, for instance if I must customize a parameter? What would be a better editor to use? I luv my TSE.
That's a new one on me, I've never seen or had any problems with text editors, I have plenty to choose from in Linux where I mainly use medit but on Windows I have used Context with a Forth highlighter, both of which you will find in the Tachyon dropbox folder (see my sigs) under PC utilities. When you mentioned QEdit it brought back images of the clunky old DOS days!!! As long as a text editor can open a file I'm happy, if it has sensible shortcut keys, I'm happy. If it has highlighting, I'm happy. Sure there are other things to look for but that's a start, otherwise I don't really have a favorite.
Output of strings over serial in tasks? Can you point out the bugz, wyht (when you have time)
Not sure what I can and can't do here re strings, the other parts work as expected
Thanks
" THE 1st STRING" $10 STRING A$
: STROUT ( str -- ) DUP LEN$ ADO I C@ 9 SEROUT LOOP ;
: MYTASK
9600d SERBAUD
" THE 2nd STRING" $10 STRING B$
#12 9 SEROUT \ clr lcd
#17 9 SEROUT \ turn on bl
#100 ms
$3A $30 DO I 9 SEROUT LOOP $47 $41 DO I 9 SEROUT LOOP \ output 0-1A-F
#2000 ms
A$ STROUT \ no joy
#2000 ms
B$ STROUT \ not this way either
#1000 ms
#12 9 SEROUT
#18 9 SEROUT
;
Tracy Allen made an integer only version of the sensirion (in spin). Maybe you can check it.
The application is a far end (90 - 100%) RH sensor in a condensing, dirty environment and sensirion, honeywell .... just can't handle the abuse. These "membrane" sensors have extremely poor resolution at the high end, not to mention drift and downright failure. Thus I must use the Saturation VP to get the best resolution via wet/dry bulb temps and ambient pressure. Tracy knows about this application and its issues.
Output of strings over serial in tasks? Can you point out the bugz, wyht (when you have time)
Not sure what I can and can't do here re strings, the other parts work as expected
Thanks
This is exactly why we have character I/O redirection for EMIT and KEY, so that we don't have to have special routines for all these displays etc.
Here's the code using redirection and also the STRING word is a defining word, you don't use it inside another definition, that was your main problem. Otherwise you can just use a literal string inside the definition without defining it.
[FONT=courier new]\ Define the emit word for this output
: LCDEMIT 9 SEROUT ;
: LCD ' LCDEMIT uemit W! ;
" THE 2nd STRING" 0 STRING B$
" HOW IS LONG IS" 0 STRING A$
: MYTASK
9600d SERBAUD
LCD
CLS \ clr lcd
#17 EMIT \ turn on bl
#100 ms
"0" #10 ADO I EMIT LOOP "A" 6 ADO I EMIT LOOP \ output 0-1A-F
2 seconds
A$ PRINT$
2 seconds
B$ PRINT$
1 second
" any old string" PRINT$
1 second
CR PRINT" That's all folks!"
1 second
CLS
#18 EMIT
CON
;
[/FONT]
EDIT: I've added a couple of lines showing a literal string and what I normally do, just print what I want to say. Notice that there are PRINT aliases for many normal Forth words, so PRINT is the "dot" word, and PRINT$ is TYPE$ and PRINT" is ." as I find that the . itself barely stands out in forums and on documents so I chose PRINT as that is instantly recognizable to anyone.
This is exactly why we have character I/O redirection for EMIT and KEY, so that we don't have to have special routines for all these displays etc.
Here's the code using redirection and also the STRING word is a defining word, you don't use it inside another definition, that was your main problem. Otherwise you can just use a literal string inside the definition without defining it.
[FONT=courier new]\ Define the emit word for this output
: LCDEMIT 9 SEROUT ;
: LCD ' LCDEMIT uemit W! ;
" THE 2nd STRING" 0 STRING B$
" HOW IS LONG IS" 0 STRING A$
: MYTASK
9600d SERBAUD
LCD
CLS \ clr lcd
#17 EMIT \ turn on bl
#100 ms
"0" #10 ADO I EMIT LOOP "A" 6 ADO I EMIT LOOP \ output 0-1A-F
2 seconds
A$ PRINT$
2 seconds
B$ PRINT$
1 second
" any old string" PRINT$
1 second
CR PRINT" That's all folks!"
1 second
CLS
#18 EMIT
CON
;
[/FONT]
EDIT: I've added a couple of lines showing a literal string and what I normally do, just print what I want to say. Notice that there are PRINT aliases for many normal Forth words, so PRINT is the "dot" word, and PRINT$ is TYPE$ and PRINT" is ." as I find that the . itself barely stands out in forums and on documents so I chose PRINT as that is instantly recognizable to anyone.
Maybe I didn't explain myself well.
' MYTASK 4 RUN \ trying to run this in a task, guess I shouldn't have left out that info. This is why I took the approach I did, I do realize all the aliases that have been created.
' MYTASK 4 RUN \ trying to run this in a task, guess I shouldn't have left out that info. This is why I took the approach I did, I do realize all the aliases that have been created.
Update: everything runs but the string values.
If you disable the LCD word in MYTASK it emits to the console which I checked a couple of different ways, it all works, the strings print etc. It doesn't matter that it runs in another task either except you need to allocate a data stack for it these days as the cog only has a depth of 4 levels and the rest is external. Here's an example of starting up a task to do nothing more than buffer some RS232 data. You can follow the way it creates a datastack and assigns that memory to the cog task.
[FONT=courier new]TABLE stack232 $40 ALLOT
TABLE buf232 $80 ALLOT
BYTE rxrd,rxwr
LONG logrcd
\ Buffer data from the RS232 port - nothing else
pub RS232_TASK
stack232 SP! !SP \ Set the stack pointer for this cog and make sure it's initalized (optional)
logbaud @ SERBAUD
DTR232 PINSET
RTS232 PINSET
TXD232 PINSET
rxrd C~ rxwr C~ buf232 $80 ERASE
BEGIN
logport C@ SERIN
rxwr C@ $7F AND buf232 + C!
rxwr C++
AGAIN
;[/FONT]
So when you are debugging stuff like your code always try to run it in the main console cog first and even direct output back to the console too. Then try the redirect to the LCD, and then finally as a task when you know everything else is working fine.
I am finding these references to aliases confusing. The only PRINT I am finding in the WORDS list is PRINT" and yet in the code you post you use PRINT" and refer to PRINT as an alias for the dot word. By this do you mean that using PRINT" instead of ." is just for clarity when communicating about code rather than writing code for execution?
Geez. I getting all muddled up just trying to ask the question.
If you disable the LCD word in MYTASK it emits to the console which I checked a couple of different ways, it all works, the strings print etc. It doesn't matter that it runs in another task either except you need to allocate a data stack for it these days as the cog only has a depth of 4 levels and the rest is external. Here's an example of starting up a task to do nothing more than buffer some RS232 data. You can follow the way it creates a datastack and assigns that memory to the cog task.
[FONT=courier new]TABLE stack232 $40 ALLOT
TABLE buf232 $80 ALLOT
BYTE rxrd,rxwr
LONG logrcd
\ Buffer data from the RS232 port - nothing else
pub RS232_TASK
stack232 SP! !SP \ Set the stack pointer for this cog and make sure it's initalized (optional)
logbaud @ SERBAUD
DTR232 PINSET
RTS232 PINSET
TXD232 PINSET
rxrd C~ rxwr C~ buf232 $80 ERASE
BEGIN
logport C@ SERIN
rxwr C@ $7F AND buf232 + C!
rxwr C++
AGAIN
;[/FONT]
So when you are debugging stuff like your code always try to run it in the main console cog first and even direct output back to the console too. Then try the redirect to the LCD, and then finally as a task when you know everything else is working fine.
What is the meaning of "pub", "pri", and "code" within the Tachyon context? Of course I know that it is "public", "private" and so on but what are the implications for the use of those words?
I am finding these references to aliases confusing. The only PRINT I am finding in the WORDS list is PRINT" and yet in the code you post you use PRINT" and refer to PRINT as an alias for the dot word. By this do you mean that using PRINT" instead of ." is just for clarity when communicating about code rather than writing code for execution?
Geez. I getting all muddled up just trying to ask the question.
The aliases are actually meant to make it clearer, not get you muddled!!! Just make sure you have the latest kernels compiled, the aliases are something I've added recently. As I mentioned the reason I have done so is because the dot symbol is hard to see in a lot of documents but PRINT punches you in the face and is well recognized.
What is the meaning of "pub", "pri", and "code" within the Tachyon context? Of course I know that it is "public", "private" and so on but what are the implications for the use of those words?
The colon word is the normal Forth defining word and pub and pri do the same thing except that pri sets a private bit in the attribute flags of the header. This does nothing normally but when I run RECLAIM it scans for any names that have the private attribute and strips them from the dictionary thus saving both precious memory and also preventing the misuse of these words normally. So pub is exactly the same as the colon but the other reason I use pub and pri is simply to make it easier to see in documents, much like the PRINT word does and also to make it recognizable to anyone who has programmed in Spin as that is the "native HLL language" of the Prop.
The "code" tag only shows up when you do a WORDS listing to identify what type of word it is.
If the data stack can exceed 4 levels by overflowing into hub memory how can you determine the size of the stack? DROP does decrease the size of the stack doesn't it?
If the data stack can exceed 4 levels by overflowing into hub memory how can you determine the size of the stack? DROP does decrease the size of the stack doesn't it?
What is the difference between BEGIN . . . UNTIL and BEGIN . . . REPEAT ?
I don't (cog-wise) waste time trying to determine if the stack is greater then 4 levels deep, it always overflows into hub RAM even if there is only one item, so the depth is determined from the stack write index. Before when I had a 12 level deep cog RAM stack all the pushing and popping was done by moving memory and there was no depth pointer. So interestingly the change to a hybrid stack hasn't actually slowed anything down as the time lost to hub access is made up for the time gained from not moving 8 cog locations. So DROP will continue to drop until the stack is empty but will stop there, the DEPTH word will tell you how deep the stack is.
As for BEGIN UNTIL vs BEGIN REPEAT, that's really BEGIN WHILE REPEAT and although I would have preferred to say BEGIN WHILE AGAIN in keeping with the simpler BEGIN AGAIN construct, it is however been a standard to use REPEAT to match up with a WHILE. So BEGIN AGAIN is a forever loop typically used in a task, BEGIN UNTIL for a conditional exit from the loop, BEGIN WHILE REPEAT for an infinite loop (REPEAT == AGAIN) except the WHILE determines what it will do and for how long. i.e. BEGIN ANY_DATA? WHILE PROCESS_DATA REPEAT
\ Here is an extremely basic Inter Task Communication example, not optimized, I didn't know if it should go into the intro doc or not.
It uses BEGIN AGAIN to run the TASK continuously.
WORD BLINKRUN \ global variable to save the state of the blinky task
#13 MASK CONSTANT RDYLED \ define a constant mask for the led pin, define your pin
: BLINKY
BEGIN
ATN@ DUP 0=
IF DROP \ no command, drop the 0 returned by ATN@ and continue
BLINKRUN W@ \ read the global variable to see what we need to do
IF
RDYLED OUTSET 100d ms RDYLED OUTCLR 100d ms \ it was ON we are running blink
ELSE
RDYLED OUTSET \ else it was OFF just set the led on
THEN
ELSE \ got a command let's check it
DUP #33 = \ dup it and check it against #33 our blink on command
IF
#33 ENQ! \ send the command back to the task that called us
ON BLINKRUN W! \ set the global variable state
THEN
#66 = \ check it against #66, use last stack item, stack clean
IF \ if so set blink off
#66 ENQ! \ echo back the command again
OFF BLINKRUN W! \ set the global variabl state
THEN
THEN
AGAIN \ do it forever
;
: BLKYINIT ' BLINKY 4 RUN \ start the BLINKY Task in COG 4 and start blinking
#33 4 ATN!
;
: BLKYSTOP #66 4 ATN! 100 ms 4 ENQ@ . ; \ send stop command,read response
: BLKYSTART #33 4 ATN! 100 ms 4 ENQ@ . ; \ send start command, read response
\ USAGE
{
DECIMAL ok
BLKYINIT ok
BLKYSTOP 66 ok
BLKYSTART 33 ok
BLKYSTOP 66 ok
}
I don't (cog-wise) waste time trying to determine if the stack is greater then 4 levels deep, it always overflows into hub RAM even if there is only one item, so the depth is determined from the stack write index. Before when I had a 12 level deep cog RAM stack all the pushing and popping was done by moving memory and there was no depth pointer. So interestingly the change to a hybrid stack hasn't actually slowed anything down as the time lost to hub access is made up for the time gained from not moving 8 cog locations. So DROP will continue to drop until the stack is empty but will stop there, the DEPTH word will tell you how deep the stack is.
As for BEGIN UNTIL vs BEGIN REPEAT, that's really BEGIN WHILE REPEAT and although I would have preferred to say BEGIN WHILE AGAIN in keeping with the simpler BEGIN AGAIN construct, it is however been a standard to use REPEAT to match up with a WHILE. So BEGIN AGAIN is a forever loop typically used in a task, BEGIN UNTIL for a conditional exit from the loop, BEGIN WHILE REPEAT for an infinite loop (REPEAT == AGAIN) except the WHILE determines what it will do and for how long. i.e. BEGIN ANY_DATA? WHILE PROCESS_DATA REPEAT
Thanks, Peter. I guess I should have searched for DEPTH in the word list. That's a no brainer - same as the hp calculators I love. I'm trying to research this stuff myself as much as possible because I know that is the best way to learn but there is an awful lot and sometimes nothing in the Intro to go on. I have "Starting Forth" standing by, the word list captured from Tachyon, and the source files and extensions. I try to check those before I post.
Looking through the v2.3 code i see a "+s" in many places being added to a label.
I did not notice were it was defined so what is that offset and why is it there?
Thanks for the education.
rich
That's the old header offset that's needed as the Spin compiler (we really only compile PASM) generates absolute addresses offset by $10 as the first 16 bytes of memory hold the clock freqency, code and stack initialization parameters etc. So any PASM source needs to add this offset if it wants the real absolute memory address.
The "s" is a lot less distracting than $10 or the like, it is defined just before the cog VM kernel about 75% through the source:
[FONT=courier new] org $10[/FONT][FONT=courier new]
[/FONT]
[FONT=courier new]s ' just an offset to be used in DAT sections rather than the distracting +$10[/FONT]
\ Here is an extremely basic Inter Task Communication example, not optimized, I didn't know if it should go into the intro doc or not.
It uses BEGIN AGAIN to run the TASK continuously.
Didn't I give you edit rights to that document? You just have to start exercising that great responsibility now!
Thanks, Peter. I guess I should have searched for DEPTH in the word list. That's a no brainer - same as the hp calculators I love. I'm trying to research this stuff myself as much as possible because I know that is the best way to learn but there is an awful lot and sometimes nothing in the Intro to go on. I have "Starting Forth" standing by, the word list captured from Tachyon, and the source files and extensions. I try to check those before I post.
Bearing in mind that the Introduction to Tachyon Forth is not really an Introduction to Forth in general please feel free to make suggestions, even compiling the suggestions into a list and posting these. If some of the suggestions are more general to Forth in nature and too wordy to include then I may just link to that material instead.
In addition to the Intro page Tachyon also needs a reference manual I guess but the reason that I haven't done one is that it is a lot of work and also the source code documents are readily available and formatted with some usage examples etc.
Thanks Peter on the "s" info. I would not have figured that out.
BTW what do mean by old header. Is there a newer file i should be studying?
cheers,
rich
old as in "ole familiar" header
The offset gets used in Tachyon when it needs to know the absolute address at compile time (it's a compiler work-around). Here the vector table needs to have the absolute address compiled so that at runtime it can just load the address from the table. The Spin operator @ returns with the address and the +s adds in the extra 16 bytes.
[FONT=courier new]xFILL long @FILL+s[/FONT]
[FONT=courier new]xERASE long @ERASE+s[/FONT]
Okay so I am able to start tasks with there own stack as you demonstrated in the RS232 snipet.
The serial task that outputs to a LCD works correctly now.
Something I'm not understanding about uemit and ukey though.
The LCD serial task starts and continously loops through the messages but the console keyboard input is vectored to the LCD
,which cause the LCD to freeze, and does not remain in the console. Issuing a CON gets the keyboard back but now the system is unstable and requires a reboot.
I thought that "calling" LCD from within the task would not vector the console's keyboard input to the LCD
: LCDEMIT 9 SEROUT ; \ define emit word for this output
: LCD ' LCDEMIT uemit W! ; \ vector it to uemit
Obviously it's my lack of understanding of uemit and ukey in tasks.
Okay so I am able to start tasks with there own stack as you demonstrated in the RS232 snipet.
The serial task that outputs to a LCD works correctly now.
Something I'm not understanding about uemit and ukey though.
The LCD serial task starts and continously loops through the messages but the console keyboard input is vectored to the LCD
,which cause the LCD to freeze, and does not remain in the console. Issuing a CON gets the keyboard back but now the system is unstable and requires a reboot.
I thought that "calling" LCD from within the task would not vector the console's keyboard input to the LCD
: LCDEMIT 9 SEROUT ; \ define emit word for this output
: LCD ' LCDEMIT uemit W! ; \ vector it to uemit
Obviously it's my lack of understanding of uemit and ukey in tasks.
Okay, as you can see from the code the only vector that was changed was the emit vector, not the key vector, so the LCD word only redirects output. What also happens though is that your task may use other common areas however what you can do is allocate memory for the Forth task variables or what I call registers. Each TF cog can point to it's own set of registers if it wants and the registers are so structured that you don't have to implement them all, the basic ones to do with redirection and number base etc are near the start of the register memory. Here is a snippet from the source:
[B][B][COLOR=#999999][FONT=Arial][B]{[/B][/FONT][/COLOR][COLOR=#000000][FONT=Arial][B]TASK REGISTERS[/B][/FONT][/COLOR][COLOR=#999999][FONT=Arial][B]}[/B][/FONT][/COLOR][/B]
[COLOR=#020FC0][FONT=Ubuntu Mono]' Task registers can be switched easily by setting "regptr" ( 7 COGREG! )[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' New tasks may only need room for the first 32 or 72 bytes[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]registers long 0[64] 'Variables used by kernel + general-purpose[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono] org 0[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono]' register offsets within "registers". Access as REG,delim ... REG,base ... etc[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono]'[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' Minimum registers required for a new task - other registers after the ' ---- are not needed other than by the console[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]temp res 12 ' general purpose[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]cntr res 4 ' hold CNT or temp[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' @16[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]uemit res 2[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]ukey res 2[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]keypoll res 2 ' poll user routines - low priority background task[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]unum res 2 ' User number processing routine - executed if number failed and UNUM <> 0[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]baudcnt res 4 ' baud cnt value where baud = clkfreq/baudcnt[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]uswitch res 4 ' target parameter used in CASE structures[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' @32[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]padwr res 1 ' write index (builds characters down from lsb to msb in MODULO style)[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]numpad res numpadsz ' Number print format routines assemble digit characters here[/FONT][/COLOR]
[/B]
Notice there are 16 bytes reserved for temp and cntr and then you have uemit and ukey so you can allocate just the memory you need. I also notice that I could still rearrange some of the other registers to move closer to the start, including base etc. To set a new register base there is the TASKREGS word in EXTEND which just performs a 7 COGREG!.
I tried some older code on the latest Dropbox (Tachyon 2.3.spin plus EXTEND and followed the "8 bit PWM" commentary and this is what happened ... every time
AUTORUN EXTEND.boot
MODULES LOADED:
1800: EXTEND.fth Primary extensions to TACHYON kernel - 140216-1400
ok
TABLE pwm #256 ALLOT ok
#1000 PWMFREQ ok
0 8 RUNPWM ok
Ŀ --> <-- NOT FOUND
Okay, as you can see from the code the only vector that was changed was the emit vector, not the key vector, so the LCD word only redirects output. What also happens though is that your task may use other common areas however what you can do is allocate memory for the Forth task variables or what I call registers. Each TF cog can point to it's own set of registers if it wants and the registers are so structured that you don't have to implement them all, the basic ones to do with redirection and number base etc are near the start of the register memory. Here is a snippet from the source:
[B][B][COLOR=#999999][FONT=Arial][B]{[/B][/FONT][/COLOR][COLOR=#000000][FONT=Arial][B]TASK REGISTERS[/B][/FONT][/COLOR][COLOR=#999999][FONT=Arial][B]}[/B][/FONT][/COLOR][/B]
[COLOR=#020FC0][FONT=Ubuntu Mono]' Task registers can be switched easily by setting "regptr" ( 7 COGREG! )[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' New tasks may only need room for the first 32 or 72 bytes[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]registers long 0[64] 'Variables used by kernel + general-purpose[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono] org 0[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono]' register offsets within "registers". Access as REG,delim ... REG,base ... etc[/FONT][/COLOR]
[COLOR=#000000][FONT=Ubuntu Mono]'[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' Minimum registers required for a new task - other registers after the ' ---- are not needed other than by the console[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]temp res 12 ' general purpose[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]cntr res 4 ' hold CNT or temp[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' @16[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]uemit res 2[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]ukey res 2[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]keypoll res 2 ' poll user routines - low priority background task[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]unum res 2 ' User number processing routine - executed if number failed and UNUM <> 0[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]baudcnt res 4 ' baud cnt value where baud = clkfreq/baudcnt[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]uswitch res 4 ' target parameter used in CASE structures[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]' @32[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]padwr res 1 ' write index (builds characters down from lsb to msb in MODULO style)[/FONT][/COLOR]
[COLOR=#020FC0][FONT=Ubuntu Mono]numpad res numpadsz ' Number print format routines assemble digit characters here[/FONT][/COLOR]
[/B]
Notice there are 16 bytes reserved for temp and cntr and then you have uemit and ukey so you can allocate just the memory you need. I also notice that I could still rearrange some of the other registers to move closer to the start, including base etc. To set a new register base there is the TASKREGS word in EXTEND which just performs a 7 COGREG!.
So how to structure this code with TASKREGS then?
TABLE stacktsk $40 ALLOT
: LCDEMIT 9 SEROUT ; \ define emit word for this output
: LCD ' LCDEMIT uemit W! ; \ vector it to uemit
" THE 2nd STRING" 0 STRING B$ \ tachyon string variable
" HOW IS LONG IS" 0 STRING A$
: MYTASK \ task to demonstrate LCD output
\ TASKREGS \ what is it about this I don't understand, need to allocate space for these I guess
stacktsk SP! !SP \ assign this task a local stack and initialize to a depth of 0
9600d SERBAUD \ set this task's BAUD
LCD \ re-vector output
BEGIN
CLS \ clr lcd
#17 EMIT \ turn on bl
#100 ms
"0" #10 ADO I EMIT LOOP "A" 6 ADO I EMIT LOOP \ output 0-1A-F
2 seconds
A$ PRINT$
2 seconds
CLS
B$ PRINT$
2 second
CLS
" any old string" PRINT$
1 second
CLS
CR PRINT" That's all folks!"
1 second
CLS
#18 EMIT \ turn off bl
1 second
AGAIN
;
I was going to leave that exercise to you but I have included the extra line or two to show you what I would do in this circumstance.
TABLE regs1 $20 ALLOT \ some room for temp register + uemit and ukey
TABLE stacktsk $40 ALLOT
: LCDEMIT 9 SEROUT ; \ define emit word for this output
: LCD ' LCDEMIT uemit W! ; \ vector it to uemit
" THE 2nd STRING" 0 STRING B$ \ tachyon string variable
" HOW IS LONG IS" 0 STRING A$
: MYTASK \ task to demonstrate LCD output
regs1 TASKREGS \ <----- setup separate task registers for this task
stacktsk SP! !SP \ assign this task a local stack and initialize to a depth of 0
9600d SERBAUD \ set this task's BAUD
LCD \ re-vector output
BEGIN
CLS \ clr lcd
#17 EMIT \ turn on bl
#100 ms
"0" #10 ADO I EMIT LOOP "A" 6 ADO I EMIT LOOP \ output 0-1A-F
2 seconds
A$ PRINT$
2 seconds
CLS
B$ PRINT$
2 second
CLS
" any old string" PRINT$
1 second
CLS
CR PRINT" That's all folks!"
1 second
CLS
#18 EMIT \ turn off bl
1 second
AGAIN
;
I was going to leave that exercise to you but I have included the extra line or two to show you what I would do in this circumstance.
TABLE regs1 $20 ALLOT \ some room for temp register + uemit and ukey
TABLE stacktsk $40 ALLOT
: LCDEMIT 9 SEROUT ; \ define emit word for this output
: LCD ' LCDEMIT uemit W! ; \ vector it to uemit
" THE 2nd STRING" 0 STRING B$ \ tachyon string variable
" HOW IS LONG IS" 0 STRING A$
: MYTASK \ task to demonstrate LCD output
regs1 TASKREGS \ <----- setup separate task registers for this task
stacktsk SP! !SP \ assign this task a local stack and initialize to a depth of 0
9600d SERBAUD \ set this task's BAUD
LCD \ re-vector output
BEGIN
CLS \ clr lcd
#17 EMIT \ turn on bl
#100 ms
"0" #10 ADO I EMIT LOOP "A" 6 ADO I EMIT LOOP \ output 0-1A-F
2 seconds
A$ PRINT$
2 seconds
CLS
B$ PRINT$
2 second
CLS
" any old string" PRINT$
1 second
CLS
CR PRINT" That's all folks!"
1 second
CLS
#18 EMIT \ turn off bl
1 second
AGAIN
;
This has been elusive for me for some reason. I'm just now proceding from FORTH/Tachyon syntax to more "how it works" stuff.
Getting past this hurdle has helped me greatly, I just couldn't glean what I needed from within the source.
Now I have renewed motivation, thanks for the "thorn removal"
UPDATE, while this has removed the keyboard issue the LCD is "no op", LCD checked with console testing? I've tried with $20,$30 ALLOT for regs1
UPDATE2****** NEED TO HAVE A BLANK LINE BETWEEN EACH ALLOT STATEMENT, ARRG I BEEN BITTEN BY THIS BEFORE! BEWARE
TABLE regs1 $20 ALLOT \ some room for temp register + uemit and ukey
TABLE stacktsk $40 ALLOT
\ shoud be
TABLE regs1 $20 ALLOT \ some room for temp register + uemit and ukey
TABLE stacktsk $40 ALLOT
Comments
That's a new one on me, I've never seen or had any problems with text editors, I have plenty to choose from in Linux where I mainly use medit but on Windows I have used Context with a Forth highlighter, both of which you will find in the Tachyon dropbox folder (see my sigs) under PC utilities. When you mentioned QEdit it brought back images of the clunky old DOS days!!! As long as a text editor can open a file I'm happy, if it has sensible shortcut keys, I'm happy. If it has highlighting, I'm happy. Sure there are other things to look for but that's a start, otherwise I don't really have a favorite.
Not sure what I can and can't do here re strings, the other parts work as expected
Thanks
The application is a far end (90 - 100%) RH sensor in a condensing, dirty environment and sensirion, honeywell .... just can't handle the abuse. These "membrane" sensors have extremely poor resolution at the high end, not to mention drift and downright failure. Thus I must use the Saturation VP to get the best resolution via wet/dry bulb temps and ambient pressure. Tracy knows about this application and its issues.
This is exactly why we have character I/O redirection for EMIT and KEY, so that we don't have to have special routines for all these displays etc.
Here's the code using redirection and also the STRING word is a defining word, you don't use it inside another definition, that was your main problem. Otherwise you can just use a literal string inside the definition without defining it.
EDIT: I've added a couple of lines showing a literal string and what I normally do, just print what I want to say. Notice that there are PRINT aliases for many normal Forth words, so PRINT is the "dot" word, and PRINT$ is TYPE$ and PRINT" is ." as I find that the . itself barely stands out in forums and on documents so I chose PRINT as that is instantly recognizable to anyone.
Maybe I didn't explain myself well.
' MYTASK 4 RUN \ trying to run this in a task, guess I shouldn't have left out that info. This is why I took the approach I did, I do realize all the aliases that have been created.
Update: everything runs but the string values.
If you disable the LCD word in MYTASK it emits to the console which I checked a couple of different ways, it all works, the strings print etc. It doesn't matter that it runs in another task either except you need to allocate a data stack for it these days as the cog only has a depth of 4 levels and the rest is external. Here's an example of starting up a task to do nothing more than buffer some RS232 data. You can follow the way it creates a datastack and assigns that memory to the cog task.
So when you are debugging stuff like your code always try to run it in the main console cog first and even direct output back to the console too. Then try the redirect to the LCD, and then finally as a task when you know everything else is working fine.
Geez. I getting all muddled up just trying to ask the question.
ACKnowledged, understood, thanks.
The aliases are actually meant to make it clearer, not get you muddled!!! Just make sure you have the latest kernels compiled, the aliases are something I've added recently. As I mentioned the reason I have done so is because the dot symbol is hard to see in a lot of documents but PRINT punches you in the face and is well recognized.
The colon word is the normal Forth defining word and pub and pri do the same thing except that pri sets a private bit in the attribute flags of the header. This does nothing normally but when I run RECLAIM it scans for any names that have the private attribute and strips them from the dictionary thus saving both precious memory and also preventing the misuse of these words normally. So pub is exactly the same as the colon but the other reason I use pub and pri is simply to make it easier to see in documents, much like the PRINT word does and also to make it recognizable to anyone who has programmed in Spin as that is the "native HLL language" of the Prop.
The "code" tag only shows up when you do a WORDS listing to identify what type of word it is.
I don't (cog-wise) waste time trying to determine if the stack is greater then 4 levels deep, it always overflows into hub RAM even if there is only one item, so the depth is determined from the stack write index. Before when I had a 12 level deep cog RAM stack all the pushing and popping was done by moving memory and there was no depth pointer. So interestingly the change to a hybrid stack hasn't actually slowed anything down as the time lost to hub access is made up for the time gained from not moving 8 cog locations. So DROP will continue to drop until the stack is empty but will stop there, the DEPTH word will tell you how deep the stack is.
As for BEGIN UNTIL vs BEGIN REPEAT, that's really BEGIN WHILE REPEAT and although I would have preferred to say BEGIN WHILE AGAIN in keeping with the simpler BEGIN AGAIN construct, it is however been a standard to use REPEAT to match up with a WHILE. So BEGIN AGAIN is a forever loop typically used in a task, BEGIN UNTIL for a conditional exit from the loop, BEGIN WHILE REPEAT for an infinite loop (REPEAT == AGAIN) except the WHILE determines what it will do and for how long. i.e. BEGIN ANY_DATA? WHILE PROCESS_DATA REPEAT
Looking through the v2.3 code i see a "+s" in many places being added to a label.
I did not notice were it was defined so what is that offset and why is it there?
Thanks for the education.
rich
It uses BEGIN AGAIN to run the TASK continuously.
Thanks, Peter. I guess I should have searched for DEPTH in the word list. That's a no brainer - same as the hp calculators I love. I'm trying to research this stuff myself as much as possible because I know that is the best way to learn but there is an awful lot and sometimes nothing in the Intro to go on. I have "Starting Forth" standing by, the word list captured from Tachyon, and the source files and extensions. I try to check those before I post.
The "s" is a lot less distracting than $10 or the like, it is defined just before the cog VM kernel about 75% through the source:
Didn't I give you edit rights to that document? You just have to start exercising that great responsibility now!
In addition to the Intro page Tachyon also needs a reference manual I guess but the reason that I haven't done one is that it is a lot of work and also the source code documents are readily available and formatted with some usage examples etc.
BTW what do mean by old header. Is there a newer file i should be studying?
cheers,
rich
old as in "ole familiar" header
The offset gets used in Tachyon when it needs to know the absolute address at compile time (it's a compiler work-around). Here the vector table needs to have the absolute address compiled so that at runtime it can just load the address from the table. The Spin operator @ returns with the address and the +s adds in the extra 16 bytes.
The serial task that outputs to a LCD works correctly now.
Something I'm not understanding about uemit and ukey though.
The LCD serial task starts and continously loops through the messages but the console keyboard input is vectored to the LCD
,which cause the LCD to freeze, and does not remain in the console. Issuing a CON gets the keyboard back but now the system is unstable and requires a reboot.
I thought that "calling" LCD from within the task would not vector the console's keyboard input to the LCD
Obviously it's my lack of understanding of uemit and ukey in tasks.
Okay, as you can see from the code the only vector that was changed was the emit vector, not the key vector, so the LCD word only redirects output. What also happens though is that your task may use other common areas however what you can do is allocate memory for the Forth task variables or what I call registers. Each TF cog can point to it's own set of registers if it wants and the registers are so structured that you don't have to implement them all, the basic ones to do with redirection and number base etc are near the start of the register memory. Here is a snippet from the source:
Notice there are 16 bytes reserved for temp and cntr and then you have uemit and ukey so you can allocate just the memory you need. I also notice that I could still rearrange some of the other registers to move closer to the start, including base etc. To set a new register base there is the TASKREGS word in EXTEND which just performs a 7 COGREG!.
[code]
Propeller .:.:--TACHYON--:.:. Forth V23140216.1600
NAMES: $5E70...74EF for 5759 (3245 bytes added)
CODE: $0000...3101 for 6786 (6401 bytes added)
CALLS: 0500 vectors free
RAM: 11631 bytes free
AUTORUN EXTEND.boot
MODULES LOADED:
1800: EXTEND.fth Primary extensions to TACHYON kernel - 140216-1400
ok
TABLE pwm #256 ALLOT ok
#1000 PWMFREQ ok
0 8 RUNPWM ok
Ŀ --> <-- NOT FOUND
So how to structure this code with TASKREGS then?
I was going to leave that exercise to you but I have included the extra line or two to show you what I would do in this circumstance.
This has been elusive for me for some reason. I'm just now proceding from FORTH/Tachyon syntax to more "how it works" stuff.
Getting past this hurdle has helped me greatly, I just couldn't glean what I needed from within the source.
Now I have renewed motivation, thanks for the "thorn removal"
UPDATE, while this has removed the keyboard issue the LCD is "no op", LCD checked with console testing? I've tried with $20,$30 ALLOT for regs1
UPDATE2****** NEED TO HAVE A BLANK LINE BETWEEN EACH ALLOT STATEMENT, ARRG I BEEN BITTEN BY THIS BEFORE! BEWARE