Another oddity.
Pasting in the EXTEND.FTH does something odd.
While transferring, it all seems to work fine (it scrolls down the screen with occasional "ok"s and other things).
At the end I get:
.DAWN#
.DAWN#
.DAWN#
.DAWN#
.DAWN#
.DAWN#
.DAWN#
.DAWN# ok
.DAWN#
End of source code, 0000 errors found
Code bytes used = 8828
CODE:$3CBC = 15036 bytes
NAME:$57D2 = 7214 bytes
DATA:$7678 = 360 bytes
FREE: = 6934 bytes
Data Stack (0)
ok
DAWN#
DAWN#
DAWN# errors W@ 0= IF SAVEROMS THEN
At that point, I can no longer do anything in the terminal.
Looking at the end of the EXTENT file I can see the "errors" line and that there are a few more lines to process but it doesn't seem to get through it.
I'm suspecting maybe some line ending misconfiguration in the terminal?? maybe??
Other things work fine, such as doing some math and stack actions.
DAWN# 3 4 5 + - .s Data Stack (1)
$FFFF.FFFA - -6
ok
DAWN#
@thej - which terminal program are you using? Did you try issuing a break condition to see what happens?
Either way it wouldn't hurt to download the very latest update and make sure it has the correct clock selected as I have just been testing with that without any problems. I'm updating EXTEND eventually to use a newer number print format in place of PRINTNUM etc using format strings.
I'm using CoolTerm.
Sending a break seems to have reset the board as I got the Tachyon intro title.
Typing in some of the words that are in extend just give me ??? so it doesn't appear that they are in the dictionary.
I have been experimenting with formatting numbers by supplying a format string instead of the fixed PRINTNUM routine that I have been using.This is mainly for use with the P2 but I have been playing with it on the P1. Essentially you can format the printing of a number simply by using a format string where every character in it is a command or a character to insert. While nowhere near full feature as a printf it also doesn't need to be as all the flexibility for printing numbers can be had using the <# # #> primitives etc. But .AS can replace PRINTNUM and .AS is simpler and far more flexible which is better. The ability to embedded text removes the need to print text separately too. Although a format string can be passed to .AS there is a more compact version .AS" that directly embeds the string.
There are lots of things I can add, change, and improve, but already this is quite useful. Of course format strings can be built into a special word for printing currency etc or the string can be stored as a constant etc. The name is deliberately kept short to suit the maximum of six 5-bit encoded characters that will be used in TAQOZ to fit into a single long including attributes.
Here are some samples
Format currency
.. 12 .AS" $~#,###,###,##~#.##" $0.12 ok
.. 123 .AS" $~#,###,###,##~#.##" $1.23 ok
.. 1234 .AS" $~#,###,###,##~#.##" $12.34 ok
.. 123456789 .AS" $~#,###,###,##~#.##" $1,234,567.89 ok
Format date
.. 180107 .AS" 20##/##/##" 2018/01/07 ok
Format time
.. 213543 .AS" ##:##:##" 21:35:43 ok
.. 213543 .AS" The time is now ##:##:##" The time is now 21:35:43 ok
Format temperature
.. 215 .AS" The temperature is ~##~#.#'C" The temperature is 21.5'C ok
Format timing
.. 12 .AS" ###,##~#.###us" 0.012us ok
.. 123 .AS" ###,##~#.###us" 0.123us ok
.. 1234 .AS" ###,##~#.###us" 1.234us ok
.. 12345678 .AS" ###,##~#.###us" 12,345.678us ok
That's very interesting. Consistent with the way Forth works, it seems to be backwards from what you'd do in C or most other languages. Usually you "comment out" code. In this case it seems you're commenting it in. :-)
I have finally got around to updating to "Dawn - vs 4.7". I have run into a problem with an application which is reading an 8-bit data port. There appears to be no PINS@ available. Is ther a substitute for PINS@ in vs. 4.7?
I finally figured out the ROOT of the problem with programming and communicating with my P1 board... A flaky USB port!
It has not completely failed but is effectively unusable.
A mouse will be powered but will not move the cursor and a flash drive will not work at all.
However, BOTH will be recognized by the system in the System Report utility.
Connecting the board to my only other USB port (I didn't do this last time as my mouse was connected) worked !!
I am able to use PropellerIDE with MacOS 10.13.2 successfully !!! Mostly....
It's still a quirky program (crashes randomly, reports failed transfers when they worked) but it does transfer a working Tachyon 4.7 to the board.
I also set the DTS RTS to ON in CoolTerm which fixed a carriage return issue and set it to it's fastest speed (230400) and all is working!
Now I just need to re-find the correct instructions for adding EASYFILE and EXTEND then find some example code to play with :-)
I have finally got around to updating to "Dawn - vs 4.7". I have run into a problem with an application which is reading an 8-bit data port. There appears to be no PINS@ available. Is ther a substitute for PINS@ in vs. 4.7?
Nick
Reading parallel data is not a common thing and unfortunately is a lot slower than any SPI operation. However I have just put it back into extend.
--- Read input pins and right justify and mask - #P8 4 PINS@ - reads P8..P11 as a nibble
pub PINS@ ( pin for – n ) P@ ROT SHR SWAP MASK 1- AND ;
I have finally got around to updating to "Dawn - vs 4.7". I have run into a problem with an application which is reading an 8-bit data port. There appears to be no PINS@ available. Is ther a substitute for PINS@ in vs. 4.7?
Nick
if you put your 8-bit port on P0..P7
you can use the faster INA COG@
and then just write a byte
I'm trying to load EXTEND into Tachyon but I'm getting errors.
I have the january 8th version of 4v7 loaded on the board.
I re-downloaded EXTEND and EASYFILE.
The terminal (CoolTerm for Mac) is set to 230400 baud and it appears to be working fine for booting Tachyon and writing simple code.
I tried the "send file" option in coolterm to send EXTEND.
It gets to about 23% and then I get this:
I reset the board and just tried copy pasting it in and got the same thing.
I tried saving the file into an ASCII file (it opened as UTF-8) but my editor said it found 2 characters that had no ASCII form and could not convert it (both characters looked like a minus sign).
Should the text be ASCII or UTF-8?
Maybe I have the wrong version of EXTEND?
@thej - Don't forget to use a LINE delay of 10ms or so, depending upon the terminal. It is extremely unlikely that it needs more than 15ms but just so you have an idea. Make sure your file editor uses CR+LF for line endings and the file should be be plain ASCII.
btw, the error you are seeing is probably because it has dropped characters.
I will double check my settings but they should be ok.
I am running CoolTerm at it's top speed. Maybe it is not fully reliable.
I will do more testing.
I don't know if anyone has been using the embedded "ROMs" in V4.7 which include VGA, high speed UARTS, full-duplex UARTs etc but I have just made some changes to them including how they are loaded. Now it is very simple to specify loading multiple cogs from the one ROM but with each one having their own parameter table.
Here is the output of one-line of code to load up 5 cogs starting from 3 with the HSUART ROM. The parameter list starts from par1 and steps 12 bytes for each cog.
Numbers with the & symbol prefix are treated in the same way as IP addresses are specified in that each group of decimals represents a single byte so that in this case 4 parameters can be packed into a long. The 99 is just a way of saying that no pin number is assigned as these fields are converted to pin masks but anything >31 returns a null mask.
The HSUART ROM also has some MODBUS support where the CRC16 is calculated automatically for receive and transmit packets and can be read or sent via special 16-bit transmit commands.
Hi Peter,
I was using V3 and the pwm module worked well. I change to version Forth V4.7 DAWN 470180208.1720 and I can't get the pwm module to work. I set it up the same way and it and it crashes Tachyon.
TABLE 1024 pwms BYTES
%00000000_00000000_00000000_00000010 pwms 7600 pwm.start.
I checked the running task and it does not start. I loaded the stack with 4 numbers and it removes the top item. The pwm.start reboots the application. I check the code that worked under V3
and there is difference. What is the $7FFC in the module?
Hi Peter,
I was using V3 and the pwm module worked well. I change to version Forth V4.7 DAWN 470180208.1720 and I can't get the pwm module to work. I set it up the same way and it and it crashes Tachyon.
TABLE 1024 pwms BYTES
%00000000_00000000_00000000_00000010 pwms 7600 pwm.start.
I checked the running task and it does not start. I loaded the stack with 4 numbers and it removes the top item. The pwm.start reboots the application. I check the code that worked under V3
and there is difference. What is the $7FFC in the module?
Check it now, there were a couple of typos so that [PWM32] and [PWM32!] were referencing the actual RUNMOD code instead of the loader stub. My bad!
I removed the temporary pin masks variable at $7FFC even though it was safe and just gave it its own variable.
BTW - instead of a big long binary mask especially when you are only using a single pin you could just say "1 MASK" instead or even just %10 ALSO!- noticed you defined the pwms incorrectly. Simply say "256 longs pwms" to reserve a 1kB "table". You need to say "longs" to make sure it is long aligned.
Here's my test code for 16 PWMs (p0..p15).
Hi There,
I have been using the propeller programming book to help with the Tachyon words . I can't seem to make the waitlo, waithi waitcnt and delta work . I need to see a few short examples to get me on track.
Fixed delay in spin
pub toggle | Time
Time := cnt
repeat
waitcnt(Time += 50000)
!outa[0]
pub tst
50000 delta begin 1 high waitcnt 1 low waitcnt key until ; This will generate a 660us pulse not 10 ms
pub count pulsetrain ( -- ) \ Run in POS mode
\ set pin to output or LOW output
A 8 CTRMODE 1 FRQ 1 APIN 1 FLOAT
BEGIN
80000000 DELTA WAITCNT
0 PHSA COG! PHSA COG@ OLD ! PHSA COG@ NEW ! NEW OLD - COUNT !
COUNT @ . CR KEY UNTIL ;
How to code ( clkfreq + cnt ) Forth? -- clkfreq cnt@ +
@kdewey - a count of 50,000 cycles at 80MHz = 625us, not 10ms, If there are 80M clocks in a second then 10ms would be 1/100 of that or 800,000 which is what is the value required for 10ms. Of course you could just say 1 HIGH 10 ms 1 LOW since you are only interested in the pulse time, not the cycle time.
Obviously the code snippet
pub count pulsetrain
has not been run since the name of the function would be count and not "count pulsetrain" although in Forth and Tachyon especially we avoid those long_long_long_names as it is better to think about a name that is short and succinct.
DELTA not only preloads the delta register but also executes the first WAITCNT so following DELTA with WAITCNT results in two, not one WAITCNT. So Delta does the while cycles+cnt thing itself. Have a look at the source code (it's one of a handful that are implemented in LMM):
' DELTA ( delta -- ) Calculate and set the cnt delta and waitcnt
word 0
DELTA word LMM
call #POPX
mov deltaR,X ' use otherwise unused video reg for delta
mov cnt,X
add cnt,cnt
waitcnt cnt,deltaR ' continue from last count (must be called before target is reached)
jmp #EXIT
But once again if all you want to do is wait one second then just say "1 s" (I used to have the two words, second, and seconds, but simply saying s says it all). (Not that you want to wait 1s in your code but just letting you know)
There are btw, so many ways to measure frequency. In fact I might just put a flexible frequency counter into Tachyon so it's easy to use.
Don't forget to use the C code tag around any code you post to preserve it as is complete with tabs and spaces.
Finally! A bit of progress. Okay, it's not that I'd made no progress -- it's just been excruciatingly slow. I was with my friend, Rick Galinson, today and told him of my struggles. I admitted that now I know how he feels when I hand him a bit of advanced Spin code and tell him "It's easy!" He laughed and nodded in agreement.
I favor the EFX-TEK HC-8+ for my projects (yes, I designed it), so that's what I'm using as my platform. What I thought I'd try is to duplicate code that I use in Spin for the board. I started with a couple of x165 shift registers that are daisy-chained. These provide eight generic (user) inputs, and the low 8 bits of a 9-bit DMX address switch (the 9th bit connects to the Propeller).
Here's my first bit of working Tachyon. I decided to bit-bang the code instead of using SPIRD because the latter wants pins I don't have. Besides, I'd rather learn the manual way and then move into words that handle this low-level stuff.
: DMX_A8 3 ;
: X165_DO 2 ;
: X165_CLK 1 ;
: X165_LD 0 ;
: PINVAL
PIN@ 1 AND
;
: X165.SETUP
X165_LD HIGH
X165_CLK LOW
X165_DO FLOAT
;
: X165.IN
X165_LD LOW
X165_LD HIGH
0
16 FOR
1 <<
X165_DO PINVAL OR
X165_CLK HIGH
X165_CLK LOW
NEXT
;
: TTLPINS
X165.IN $FF AND
;
: DMXADDR
X165.IN 8 >>
DMX_A8 PINVAL 8 << OR
;
Is there a performance difference between defining pins the way I above versus this style?
What happens then is that the actual constant is compiled vs the : definition method which calls that "constant". Mind you though, I do use the : method as well, especially when I want to be able to change the constant at runtime.
It's good to see the "equivalent" of Spin code for educational purposes I suppose but if you want, replace these two words and try this (for educational purposes!):
I did treat myself to a hard cider -- a bit of cheat on my low-carb diet so I went with the low-sugar variety.
With the 74x165 I cannot use the LD line in the SPIPINS definition -- the code you suggested doesn't work. After a bit of play, this worked
: X165.SETUP &27.2.27.1 SPIPINS 0 HIGH ;
: X165.IN 0 LOW 0 HIGH 0 SPIRD SPIRD ;
: TTLPINS X165.IN $FF AND ;
: DMXADDR X165.IN 8 >> 3 PIN@ 1 AND 8 << OR ;
The only problem is that P27 is an available user IO pin on the HC-8+.
A few minutes later... I tried this cheat and it seems to work.
: X165.SETUP &255.2.255.1 SPIPINS 0 HIGH ;
If you use a pin value >31 it will set it as a null mask, so I use 99 for this purpose which would be
&99.2.99.1 SPIPINS
I just checked the 165 datasheet and it looks like LD low will load it so that's why it didn't work I guess by including it.
Yes, that cheat will work because of the null mask test. The DMXADDR could be simplified simply because you could just shift in 8-bits but use the 8th bit first:
Started studying the Glossary of Tachyon Words and found a couple helpful words (fast shifts) that would speed up the DMXADDR code a bit. This is where I am with the terse version
: INA[] PIN@ 1 AND ;
: X165.SETUP &99.2.99.1 SPIPINS 0 HIGH 1 LOW 2 FLOAT ;
: X165.IN 0 LOW 0 HIGH 0 SPIRD SPIRD ;
: TTLPINS X165.IN $FF AND ;
: DMXADDR X165.IN 8>> 3 INA[] 8<< OR ;
For my next hair-pulling adventure (thankfully, I have a lot of hair) I'm going to tackle a dual quadrature encoder driver that runs in a cog.
Started studying the Glossary of Tachyon Words and found a couple helpful words (fast shifts) that would speed up the DMXADDR code a bit. This is where I am with the terse version
: INA[] PIN@ 1 AND ;
: X165.SETUP &99.2.99.1 SPIPINS 0 HIGH 1 LOW 2 FLOAT ;
: X165.IN 0 LOW 0 HIGH 0 SPIRD SPIRD ;
: TTLPINS X165.IN $FF AND ;
: DMXADDR X165.IN 8>> 3 INA[] 8<< OR ;
For my next hair-pulling adventure (thankfully, I have a lot of hair) I'm going to tackle a dual quadrature encoder driver that runs in a cog.
Great! that encoder should be capable of running at a very high speed even without using counters. If speed is low it could even run off a timer alarm whereby timers are checked every 1ms and you can set the timeout value and an "ALARM" function.
I will have to have a look at the glossary to make sure it is up to date. The single operation multiple shift such as 8<< are 4 times faster and half the size of the discrete operations since it doesn't have to push and pop the data stack. That's the main reason for these combined operators and sometimes I think it would be nice to have a preprocessor to pick out these sequences but then again it would have to run on the Prop itself which can't spare those resources.
SPIPINS takes care of setting up inputs and outputs so that data out is low and the clock is always a low output. By default then it clocks data on low/high but since the SPI routines simply and deliberately toggle the clock line you can preset it high for those systems that need a high/low.
Now how about this version that always reads A8 first before shifting serial data in so that it ends up at b16. Also since SPIPINS sets up pin direction we could skip manually setting them and even be sneaky and have the LD pin as the MOSI pin which will be set low by SPIPINS but not used by SPIRD? It probably doesn't even need to be set since this is the first thing that X165.IN does anyway. >B converts a value to a byte, same as $FF AND.
Timing code is easy, just enclose it in LAP words and then print the lap result with .LAP. These are the results at 80MHz (on V5 though).
... LAP X165.SETUP LAP .LAP 2,048 cycles = 25.600us ok
... LAP X165.IN LAP .LAP 1,296 cycles = 16.200us ok
... LAP TTLPINS LAP .LAP 1,456 cycles = 18.200us ok
... LAP DMXADDR LAP .LAP 1,472 cycles = 18.400us ok
Great! that encoder should be capable of running at a very high speed even without using counters. If speed is low it could even run off a timer alarm whereby timers are checked every 1ms and you can set the timeout value and an "ALARM" function.
Is there a tutorial somewhere that explains the use of timers and how to link a timer to other code?
Now how about this version that always reads A8 first before shifting serial data in so that it ends up at b16.
Yep, good idea -- I updated the source Spin code, too, and saved a few microseconds
Is there a tutorial somewhere that explains the use of timers and how to link a timer to other code?
While I'm updating the intro page here are a few examples.
Create a timer structure
TIMER mytimer
To set the timer to count down 100ms
100 mytimer TIMEOUT
This will link mytimer in with any other timers that get serviced by the timer cog. Every millisecond the list of timers are counted down if non-zero and once they transition to zero an alarm vector in the timer structure is checked and executed if set. If I wanted an LED on P0 to blink for 100 ms but didn't want to sit around waiting for it I could do this with mytimer.
0 LOW (turn LED on)
100 mytimer TIMEOUT
and if I setup an alarm, which could be set up once at startup...
: LEDOFF 0 HIGH ;
' LEDOFF mytimer ALARM
Then when mytimer transitions to zero it will execute LEDOFF.
If though you want something polled every 100ms you would then have the alarm function setup as a polling function if it also reloads the timer. Have a look at this simple example which toggles an LED from a button.
TIMER mytimer
: RunStop
( Reload timer to check again in 100ms )
100 mytimer TIMEOUT
( is button pressed? )
1 PIN@ 0=
( then toggle LED on P0 )
IF 0 PIN@
IF 0 LOW ELSE 0 HIGH THEN
THEN
;
( During setup set alarm code )
' RunStop mytimer ALARM
( then trip with any timeout )
1 mytimer TIMEOUT
I even have one single timer checking 12 LEDs for timeouts as they are used to indicate activity on multiple communications ports. Each channel has two red/green LEDs and one stays on for a second with any valid activity on that channel while another one flashes for 50ms when data is received. This way I can see that the channel is active and when data comes in. The important thing to observe about timers is since they are called every 1ms is that the alarm function should be quick about its business, take much less than 1ms (easy enough), and that it has control of any outputs (don't try to exercise those outputs from another cog).
Comments
Pasting in the EXTEND.FTH does something odd.
While transferring, it all seems to work fine (it scrolls down the screen with occasional "ok"s and other things).
At the end I get:
At that point, I can no longer do anything in the terminal.
Looking at the end of the EXTENT file I can see the "errors" line and that there are a few more lines to process but it doesn't seem to get through it.
I'm suspecting maybe some line ending misconfiguration in the terminal?? maybe??
Other things work fine, such as doing some math and stack actions.
DAWN# 3 4 5 + - .s Data Stack (1)
$FFFF.FFFA - -6
ok
DAWN#
Either way it wouldn't hurt to download the very latest update and make sure it has the correct clock selected as I have just been testing with that without any problems. I'm updating EXTEND eventually to use a newer number print format in place of PRINTNUM etc using format strings.
Sending a break seems to have reset the board as I got the Tachyon intro title.
Typing in some of the words that are in extend just give me ??? so it doesn't appear that they are in the dictionary.
I'll dl the latest versions :-)
I have been experimenting with formatting numbers by supplying a format string instead of the fixed PRINTNUM routine that I have been using.This is mainly for use with the P2 but I have been playing with it on the P1. Essentially you can format the printing of a number simply by using a format string where every character in it is a command or a character to insert. While nowhere near full feature as a printf it also doesn't need to be as all the flexibility for printing numbers can be had using the <# # #> primitives etc. But .AS can replace PRINTNUM and .AS is simpler and far more flexible which is better. The ability to embedded text removes the need to print text separately too. Although a format string can be passed to .AS there is a more compact version .AS" that directly embeds the string.
There are lots of things I can add, change, and improve, but already this is quite useful. Of course format strings can be built into a special word for printing currency etc or the string can be stored as a constant etc. The name is deliberately kept short to suit the maximum of six 5-bit encoded characters that will be used in TAQOZ to fit into a single long including attributes.
Here are some samples
Format currency Format date Format time Format temperature Format timing Miscellaneous
Special character commands are:
Nick
I finally figured out the ROOT of the problem with programming and communicating with my P1 board... A flaky USB port!
It has not completely failed but is effectively unusable.
A mouse will be powered but will not move the cursor and a flash drive will not work at all.
However, BOTH will be recognized by the system in the System Report utility.
Connecting the board to my only other USB port (I didn't do this last time as my mouse was connected) worked !!
I am able to use PropellerIDE with MacOS 10.13.2 successfully !!! Mostly....
It's still a quirky program (crashes randomly, reports failed transfers when they worked) but it does transfer a working Tachyon 4.7 to the board.
I also set the DTS RTS to ON in CoolTerm which fixed a carriage return issue and set it to it's fastest speed (230400) and all is working!
Now I just need to re-find the correct instructions for adding EASYFILE and EXTEND then find some example code to play with :-)
Finally! I get to play !
J
Reading parallel data is not a common thing and unfortunately is a lot slower than any SPI operation. However I have just put it back into extend.
you can use the faster INA COG@
and then just write a byte which saves you the mask and shift operations
I have the january 8th version of 4v7 loaded on the board.
I re-downloaded EXTEND and EASYFILE.
The terminal (CoolTerm for Mac) is set to 230400 baud and it appears to be working fine for booting Tachyon and writing simple code.
I tried the "send file" option in coolterm to send EXTEND.
It gets to about 23% and then I get this:
I reset the board and just tried copy pasting it in and got the same thing.
I tried saving the file into an ASCII file (it opened as UTF-8) but my editor said it found 2 characters that had no ASCII form and could not convert it (both characters looked like a minus sign).
Should the text be ASCII or UTF-8?
Maybe I have the wrong version of EXTEND?
J
btw, the error you are seeing is probably because it has dropped characters.
I am running CoolTerm at it's top speed. Maybe it is not fully reliable.
I will do more testing.
j
Here is the output of one-line of code to load up 5 cogs starting from 3 with the HSUART ROM. The parameter list starts from par1 and steps 12 bytes for each cog. This code takes 39ms to find the ROM in EEPROM, load it into a buffer, and load 5 cogs from that buffer with their parameters.
The parameter list consists of 5 entries of 3 longs each (one as 2 words) as in this example: Numbers with the & symbol prefix are treated in the same way as IP addresses are specified in that each group of decimals represents a single byte so that in this case 4 parameters can be packed into a long. The 99 is just a way of saying that no pin number is assigned as these fields are converted to pin masks but anything >31 returns a null mask.
The HSUART ROM also has some MODBUS support where the CRC16 is calculated automatically for receive and transmit packets and can be read or sent via special 16-bit transmit commands.
These are the current ROMS in V4.7 btw:
I was using V3 and the pwm module worked well. I change to version Forth V4.7 DAWN 470180208.1720 and I can't get the pwm module to work. I set it up the same way and it and it crashes Tachyon.
TABLE 1024 pwms BYTES
%00000000_00000000_00000000_00000010 pwms 7600 pwm.start.
I checked the running task and it does not start. I loaded the stack with 4 numbers and it removes the top item. The pwm.start reboots the application. I check the code that worked under V3
and there is difference. What is the $7FFC in the module?
Check it now, there were a couple of typos so that [PWM32] and [PWM32!] were referencing the actual RUNMOD code instead of the loader stub. My bad!
I removed the temporary pin masks variable at $7FFC even though it was safe and just gave it its own variable.
BTW - instead of a big long binary mask especially when you are only using a single pin you could just say "1 MASK" instead or even just %10
ALSO!- noticed you defined the pwms incorrectly. Simply say "256 longs pwms" to reserve a 1kB "table". You need to say "longs" to make sure it is long aligned.
Here's my test code for 16 PWMs (p0..p15).
UPDATES: Renamed SETPWM to simply PWM.
Thanks for looking at my problem, where should I get the new files?
Ken
GoodDay...
I have been using the propeller programming book to help with the Tachyon words . I can't seem to make the waitlo, waithi waitcnt and delta work . I need to see a few short examples to get me on track.
Fixed delay in spin
pub toggle | Time
Time := cnt
repeat
waitcnt(Time += 50000)
!outa[0]
pub tst
50000 delta begin 1 high waitcnt 1 low waitcnt key until ; This will generate a 660us pulse not 10 ms
pub count pulsetrain ( -- ) \ Run in POS mode
\ set pin to output or LOW output
A 8 CTRMODE 1 FRQ 1 APIN 1 FLOAT
BEGIN
80000000 DELTA WAITCNT
0 PHSA COG! PHSA COG@ OLD ! PHSA COG@ NEW ! NEW OLD - COUNT !
COUNT @ . CR KEY UNTIL ;
How to code ( clkfreq + cnt ) Forth? -- clkfreq cnt@ +
Thanks Ken
Obviously the code snippet has not been run since the name of the function would be count and not "count pulsetrain" although in Forth and Tachyon especially we avoid those long_long_long_names as it is better to think about a name that is short and succinct.
DELTA not only preloads the delta register but also executes the first WAITCNT so following DELTA with WAITCNT results in two, not one WAITCNT. So Delta does the while cycles+cnt thing itself. Have a look at the source code (it's one of a handful that are implemented in LMM):
But once again if all you want to do is wait one second then just say "1 s" (I used to have the two words, second, and seconds, but simply saying s says it all). (Not that you want to wait 1s in your code but just letting you know)
There are btw, so many ways to measure frequency. In fact I might just put a flexible frequency counter into Tachyon so it's easy to use.
Don't forget to use the C code tag around any code you post to preserve it as is complete with tabs and spaces.
I favor the EFX-TEK HC-8+ for my projects (yes, I designed it), so that's what I'm using as my platform. What I thought I'd try is to duplicate code that I use in Spin for the board. I started with a couple of x165 shift registers that are daisy-chained. These provide eight generic (user) inputs, and the low 8 bits of a 9-bit DMX address switch (the 9th bit connects to the Propeller).
Here's my first bit of working Tachyon. I decided to bit-bang the code instead of using SPIRD because the latter wants pins I don't have. Besides, I'd rather learn the manual way and then move into words that handle this low-level stuff.
Is there a performance difference between defining pins the way I above versus this style?
Btw, you can code constants with the == symbol which is equivalent to CONSTANT in Forth. What happens then is that the actual constant is compiled vs the : definition method which calls that "constant". Mind you though, I do use the : method as well, especially when I want to be able to change the constant at runtime.
It's good to see the "equivalent" of Spin code for educational purposes I suppose but if you want, replace these two words and try this (for educational purposes!):
BTW, congratulations - have a drink on me!
With the 74x165 I cannot use the LD line in the SPIPINS definition -- the code you suggested doesn't work. After a bit of play, this worked The only problem is that P27 is an available user IO pin on the HC-8+.
A few minutes later... I tried this cheat and it seems to work. I'm guessing that this code gets called by SPIPINS, though I can't seem to find it: Any value over 31 would create an empty mask, but I'm going to use 255 as a "this pin not used" flag.
If you use a pin value >31 it will set it as a null mask, so I use 99 for this purpose which would be I just checked the 165 datasheet and it looks like LD low will load it so that's why it didn't work I guess by including it.
Yes, that cheat will work because of the null mask test. The DMXADDR could be simplified simply because you could just shift in 8-bits but use the 8th bit first: Of course you could factor out the load:
I'll use 99, too. Makes sense, one less character to type.
Don't worry, your subconscious will kick in while you are asleep and rewire your brain for you so it will all make sense in the morning!
For my next hair-pulling adventure (thankfully, I have a lot of hair) I'm going to tackle a dual quadrature encoder driver that runs in a cog.
Great! that encoder should be capable of running at a very high speed even without using counters. If speed is low it could even run off a timer alarm whereby timers are checked every 1ms and you can set the timeout value and an "ALARM" function.
I will have to have a look at the glossary to make sure it is up to date. The single operation multiple shift such as 8<< are 4 times faster and half the size of the discrete operations since it doesn't have to push and pop the data stack. That's the main reason for these combined operators and sometimes I think it would be nice to have a preprocessor to pick out these sequences but then again it would have to run on the Prop itself which can't spare those resources.
SPIPINS takes care of setting up inputs and outputs so that data out is low and the clock is always a low output. By default then it clocks data on low/high but since the SPI routines simply and deliberately toggle the clock line you can preset it high for those systems that need a high/low.
Now how about this version that always reads A8 first before shifting serial data in so that it ends up at b16. Also since SPIPINS sets up pin direction we could skip manually setting them and even be sneaky and have the LD pin as the MOSI pin which will be set low by SPIPINS but not used by SPIRD? It probably doesn't even need to be set since this is the first thing that X165.IN does anyway. >B converts a value to a byte, same as $FF AND.
Timing code is easy, just enclose it in LAP words and then print the lap result with .LAP. These are the results at 80MHz (on V5 though).
Yep, good idea -- I updated the source Spin code, too, and saved a few microseconds
While I'm updating the intro page here are a few examples.
Create a timer structure To set the timer to count down 100ms This will link mytimer in with any other timers that get serviced by the timer cog. Every millisecond the list of timers are counted down if non-zero and once they transition to zero an alarm vector in the timer structure is checked and executed if set. If I wanted an LED on P0 to blink for 100 ms but didn't want to sit around waiting for it I could do this with mytimer.
and if I setup an alarm, which could be set up once at startup... Then when mytimer transitions to zero it will execute LEDOFF.
If though you want something polled every 100ms you would then have the alarm function setup as a polling function if it also reloads the timer. Have a look at this simple example which toggles an LED from a button.
I even have one single timer checking 12 LEDs for timeouts as they are used to indicate activity on multiple communications ports. Each channel has two red/green LEDs and one stays on for a second with any valid activity on that channel while another one flashes for 50ms when data is received. This way I can see that the channel is active and when data comes in. The important thing to observe about timers is since they are called every 1ms is that the alarm function should be quick about its business, take much less than 1ms (easy enough), and that it has control of any outputs (don't try to exercise those outputs from another cog).
I got the WHEELCNT words working. After installing as a task it does not work.
Ken
LONG COUNTER \ hold the wheel count
pub WHEELCNT ( --- )
1 MASK 4 COG! --- setup for WAITCNT
A 1 APIN
1 FRQ
12 CTRMODE --- NEGEDGE mode
0 COUNTER ! --- Zero counter
1 FLOAT
BEGIN
--- CLKFREQ 400000 / DELTA WAITCNT
WAITHI WAITLO
COUNTER ++
COUNTER @ DUP 56 = IF
0 COUNTER ! THEN . CR --- set pulse number here
AGAIN ;
' WHEELCNT TASK? RUN
pub DSP BEGIN COUNTER @ . CR KEY UNTIL ;