Debug and explore your hardware the easy way!

How many times have we seen posts where some poor soul can't seem to get hardware working correctly or even just to blink some LED? I've decided to release a basic version of Tachyon that also includes some reporting enhancements for just this purpose. The idea is that the binary image can be loaded onto the troublesome PCB and as long as the crystal is 5 or 10Mhz (6MHz version now included) the system will boot up and communicate with the serial terminal at 115,200 baud (seems to be the limit for some terminals).
Using simple commands the user can list various parts of the hardware or just even scan everything with a lshw command (no super-user required
!).
Port pins are tested for pull-up or pull-down or float and this is reported back in the pin state map.
So even the I2C bus is included and it even tries to report what type of chip it might be, in general.
Even if they just want to blink an LED on P5 you could type "5 BLINK" and it will blink in the background at 2 Hz. Type 5 HZ and it will go faster. Type 10 MHZ and you will generate some RFI.
EXPLORER-5-10MHZ.binary 5 or 10MHz binary115200 baud
EXPLORER-6MHZ.binary 6MHz binary
Here is the output from the lshw command:
EDIT: Of course there are all the memory dumps and manipulation commands, for hub or cog or EEPROM. The are other drivers built-in which do multi-channel PWM, duty-mode DAC into RC filters, MCP3208 ADC, SPI, SERIAL etc. Other drivers can be pasted in through the terminal for character and graphic LCDs, RTCs, NeoPixels, etc and don't forget SD and FAT32 and WIZnet support although as I said these haven't been loaded into this debugger by default.
To set a pin high or low, say pin 12 high and 11 low, just type:
12 HIGH 11 LOW
To test an RC DAC on P4 and set it to half Vdd:
128 4 DAC!
Example of a Q&D (quick and dirty) one-liner to ramp the DAC continually:
BEGIN 0 256 ADO I 4 DAC! LOOP AGAIN
This is Q&D as the only way to get back to the console is to send a break (can your terminal do that?) or just reset
That loop might be a little fast, to slow it down:
BEGIN 0 256 ADO I 4 DAC! 10 ms LOOP AGAIN
Simple as that!
To let lshw run automatically at boot just type:
AUTORUN lshw
To turn it off again:
AUTORUN CANCEL
Using simple commands the user can list various parts of the hardware or just even scan everything with a lshw command (no super-user required

Port pins are tested for pull-up or pull-down or float and this is reported back in the pin state map.
So even the I2C bus is included and it even tries to report what type of chip it might be, in general.
Even if they just want to blink an LED on P5 you could type "5 BLINK" and it will blink in the background at 2 Hz. Type 5 HZ and it will go faster. Type 10 MHZ and you will generate some RFI.
EXPLORER-5-10MHZ.binary 5 or 10MHz binary115200 baud
EXPLORER-6MHZ.binary 6MHz binary
Here is the output from the lshw command:
lshw
FREQ: 80,000,000 (PLLEN OSCEN XTAL1 PLL8X )
PORT PINS
+--------------------------------+
P00 inp H up || H inp P31
P01 inp L down || H out P30
P02 inp H up || up H inp P29
P03 inp L down || float H inp P28
P04 inp L float || float L inp P27
P05 inp L float || up H inp P26
P06 inp L float || up H inp P25
P07 inp H up || down L inp P24
P08 inp H up || float L inp P23
P09 inp H up || float L inp P22
P10 inp H up || float L inp P21
P11 inp H up || float L inp P20
P12 inp L float || float L inp P19
P13 inp L float || float L inp P18
P14 inp L float || float L inp P17
P15 inp L float || float L inp P16
+--------------------------------+
COG #0 registers
01F0: PAR = $0000_17E8 %0000_0000_0000_0000_0001_0111_1110_1000
01F1: CNT = $6C82_A187 %0110_1100_1000_0010_1010_0001_1000_0111
01F2: INA = $F600_0F85 %1111_0110_0000_0000_0000_1111_1000_0101
01F3: INB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000
01F4: OUTA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000
01F5: OUTB = $0000_0146 %0000_0000_0000_0000_0000_0001_0100_0110
01F6: DIRA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000
01F7: DIRB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000
01F8: CTRA = $0580_0000 %0000_0101_1000_0000_0000_0000_0000_0000
01F9: CTRB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000
01FA: FRQA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000
01FB: FRQB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000
01FC: PHSA = $8000_0000 %1000_0000_0000_0000_0000_0000_0000_0000
01FD: PHSB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000
01FE: VCFG = $2000_0000 %0010_0000_0000_0000_0000_0000_0000_0000
01FF: VSCL = $0000_18F6 %0000_0000_0000_0000_0001_1000_1111_0110
Scanning I2C bus
Fast I/O EXPANDER #0 at 0040: 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E
Fast 64K BOOT EEPROM at 00A0: 45 80 81 0F 04 4C 4F 4E 47 A2 C3 20 04 48 49 47
Fast EEPROM or RTC #7 at 00AE: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
Fast RTC/ADC? #7 at 00DE: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ok
EDIT: Of course there are all the memory dumps and manipulation commands, for hub or cog or EEPROM. The are other drivers built-in which do multi-channel PWM, duty-mode DAC into RC filters, MCP3208 ADC, SPI, SERIAL etc. Other drivers can be pasted in through the terminal for character and graphic LCDs, RTCs, NeoPixels, etc and don't forget SD and FAT32 and WIZnet support although as I said these haven't been loaded into this debugger by default.
To set a pin high or low, say pin 12 high and 11 low, just type:
12 HIGH 11 LOW
To test an RC DAC on P4 and set it to half Vdd:
128 4 DAC!
Example of a Q&D (quick and dirty) one-liner to ramp the DAC continually:
BEGIN 0 256 ADO I 4 DAC! LOOP AGAIN
This is Q&D as the only way to get back to the console is to send a break (can your terminal do that?) or just reset
That loop might be a little fast, to slow it down:
BEGIN 0 256 ADO I 4 DAC! 10 ms LOOP AGAIN
Simple as that!
To let lshw run automatically at boot just type:
AUTORUN lshw
To turn it off again:
AUTORUN CANCEL
Comments
yes. @Peter this is the second time you made me smile this year. Please continue, I need it.
Interesting concept. Throw Tachyon at it to check your hardware before applying whatever software you want to write. To get the 'feel' of the hardware.
Debugger is the wrong term. We need cooperate speak here - hmm - interactive hardware testing? Somewhere we need the word synergy in the description and all is well.
A while ago I looked at your code to detect 5 or 10 Mhz crystals. Just curious since I gave up on Forth again last year. But I still hope to grook it at one time. So I do not give up. Any chance to detect 6 and 6.25 Mhz also?
But lately you opened up a door for me (and other non forthers). Using forth programmed props as intelligent serial/SPI/TCP/I2C/whatever extenders. You can use any language to talk to them.
Your Ethernet module is the one itching me most, but the result is the same with other variants of the idea. Preconfigured device with cmd-like interface over various protocols. If one user needs to get deeper into the firmware he can. If NOT he has a set of commands to use this preconfigured device.
Simply brilliant for people who want to 'plug things together' and then write some code around it.
Your wrong named 'debugger' is going in the right direction. Throw it at the hardware and explore/test it with some commands. Extend commands to have a 'scripted' test for your hardware.
Very cool.
Enjoy!
Mike
As you desire, a 6MHz binary (see top post) which I can use on my +P8 modules. I don't think there really is an easy way to detect smaller crystal frequency variations automatically without some other kind of reference.
Let me know if there are some utilities you would like included. Then again, it's easy to roll your own or just do a Q&D one-liner.
I also use 6.0MHz too sometimes. And I know some use 6.25MHz as that gives 100MHz.
I cannot see how to easily detect the xtal speed other than big spreads like 5 vs 10.
Perhaps you could do autoboarding on a "space" character.
A lot of the equipment I have installed or serviced has included software to verify the hardware is working correctly and to help find the problems when something fails. In general they have been called "Hardware Diagnostics". Since Forth is an interactive language/OS that is built from small co-operating routines calling a hardware debugging program like this a "Synergistic Interactive Hardware Diagnostic" would be apropriate even if it is quite a mouthful. Maybe Sid for brevity.
So whenever I get new chips most of them are either SPI or I2C and all these words are built into Tachyon as the SPI words are opcodes so they run around 4MHz clock rate. Just setup the pins in decimal byte notation (like IP) in the form select.miso.mosi.sck such as in the case of the IOT5500 I could interactively assign the pins with &17.01.19.18 SPIPINS without requiring the header file beforehand. P17 is the chip select, P18 is the clock, P19 is MOSI, and P1 is MISO.
What do we call it? Well it is just my Tachyon Forth kernel to me but with some emphasis on dressing up and standardizing the hardware debug/diagnostic/exploring which btw is the same as the standard kernel. I do have a compile time switch EXPLORER which when I load EXTEND.fth may compile some little extras and be more verbose but since many of my systems have 64K EEPROM and I compact the dictionary into the top of this now, I am not overly worried about running out of memory. Of course the explorer build doesn't have all the extra modules loaded so doesn't need to compact the dictionary and is able to run quite fine with the standard 32K EEPROM.
BTW, previously before I would normally load a SMALL version of EXTEND.fth, not just because of not having enough memory once I loaded a full network system, but also because TF would run out of execution vectors but now since I implemented the CALL16 method to take over when vectors are exhausted I find I can load even this bloated explorer version of EXTEND plus file and networking and still have memory left over.
As for autobauding, I am playing with it and just want it to be reliable. My take on this is that if the system baud-rate is set to 0 (compile-time) then the system will at boot monitor the receive line and time the intervals in a <CR> until they match-up. Then it will use this timing to lock the baud-rate and reboot (to reload the receive cog). Hopefully the system should always work correctly but it's a pain if for some reason it gets set to the wrong baud-rate and there is no way to tell what the real clock frequency is unless of course we always autobaud against actuall 115,200 baud data. Now that would enable the system to set its correct clock frequency too!
Or call it a "Synergistic Hardward Interactive Tester", That would be easier to remember the acronym.
ROFLMAO !!!!
It worked on me.
Played with Forth for the very first time because of this.
I've heard such systems called Board-Bring-Up and a subset of that is Power on Self test (POST)
A logical extension for a forth version, would be adding the ability to generate pulses of string defined length,
and other time-domain operations that a PC is quite poor at.
The Prop becomes a smarter-terminal, and can be used to provide stimulus & measure of another board (which could be running user code, or the same BBU on a separate serial link )
@jmg: Now as for a string of pulses that has got to be the easiest thing in the world to do, a Q&D one-liner that takes only a few seconds to type in.
Generate a 10 pulses for 1 second on pin 4:
4 APIN 10 HZ 1 SECOND MUTE
which uses one of the counters but this works just as well:
10 FOR 4 HIGH 50 ms 4 LOW 50 ms NEXT
Or turn the second method into a general-purpose method and lock it into the system:
pub PULSES ( pin ms-cycle cnt -- ) FOR OVER HIGH DUP 2/ ms OVER LOW DUP 2/ ms NEXT 2DROP ;
Testing it out:
4 100 10 PULSES
will generate 10 pulses with a cycle time of 100 ms on pin 4
Now back it up so that it's part of the system for next time we power-up:
BACKUP
Once again, too simple.
"Synergistic Hardward Interactive Tester". Hmmm....we will have to consult with marketing on that one.
Back in the day we created such initial code for new boards in assembler and blew it into a few K or EPROM. Such things were called a "debug monitor" or "monitor". They allowed for testing RAM and other peripherals using simple commands, entering new code (often in hexadecimal), saving code/data to tape, bootstrapping an application and so on.
That hexadecimal thing was a bit of hard work though which is where using Forth as a **** becomes an attractive option.
Yeah, marketing would know, they are full of it after all
Those debug monitors were always so frustrating and you had to know the memory location of all the I/O and variables and although it was possible to write a small machine code program, it was also very frustrating and time consuming, one little mistake and start again. I thought at the time it would be nice to have little macros that you could execute but along came Forth and blew all that away. In fact the first Forth I used on a micro only took up about 2K IIRC, hardly more than a monitor.
Now it is called EEFI, the new replacement for bios. working with FASM lately and exploring bare metal OS on x86 I stumbled upon.
To me it looks quite like a forth kernel. Need to investigate further...
Enjoy!
Mike
Now if anyone is interested could you please run lshw for your board and submit results so I can build up a database to build into Tachyon itself so it can perform this auto hardware detection.
I am also looking at building in little applets into Explorer such as capacitance and resistance meters, LCD drivers with hardware configuration menu etc. Just looking at making it so easy to connect and configure without having to search through the obex and then trying to figure out how to interface it as you normally would in Spin.
So this is an example of running lshw from one of my boards: (don't forget to put the listing into [ code ] tags to preserve the content)
lshw FREQ: 80MHZ (PLLEN OSCEN XTAL1 PLL8X ) PORT PINS +--------------------------------+ P00 inp H up || H inp P31 P01 inp L down || H out P30 P02 inp H up || up H inp P29 P03 inp L down || float L inp P28 P04 inp L float || float L inp P27 P05 inp L float || up H inp P26 P06 inp L float || up H inp P25 P07 inp H up || down L inp P24 P08 inp L down || float L inp P23 P09 inp H float || float L inp P22 P10 inp L down || float L inp P21 P11 inp L down || float L inp P20 P12 inp L float || float L inp P19 P13 inp L float || float L inp P18 P14 inp L float || float L inp P17 P15 inp L float || float L inp P16 +--------------------------------+ COG #0 registers $01F0: PAR = $0000_17E8 %0000_0000_0000_0000_0001_0111_1110_1000 $01F1: CNT = $02A3_0295 %0000_0010_1010_0011_0000_0010_1001_0101 $01F2: INA = $E600_0085 %1110_0110_0000_0000_0000_0000_1000_0101 $01F3: INB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01F4: OUTA = $7000_0000 %0111_0000_0000_0000_0000_0000_0000_0000 $01F5: OUTB = $0000_0146 %0000_0000_0000_0000_0000_0001_0100_0110 $01F6: DIRA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000 $01F7: DIRB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01F8: CTRA = $0580_0000 %0000_0101_1000_0000_0000_0000_0000_0000 $01F9: CTRB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01FA: FRQA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000 $01FB: FRQB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01FC: PHSA = $8000_0000 %1000_0000_0000_0000_0000_0000_0000_0000 $01FD: PHSB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01FE: VCFG = $2000_0000 %0010_0000_0000_0000_0000_0000_0000_0000 $01FF: VSCL = $0000_18F6 %0000_0000_0000_0000_0001_1000_1111_0110 Scanning I2C bus Fast I/O EXPANDER #0 at $40: 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E 3E Fast 64K BOOT EEPROM at $A0: 45 80 81 0F 04 4C 4F 4E 47 A2 C3 21 04 48 49 47 Fast EEPROM or RTC #7 at $AE: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF Fast RTC/ADC? #7 at $DE: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ok
Here are my scans from a QuickStart Board, (#40000), by itself, with the HID board, (#40003), with the Memory Board(#40004), with and without the uSD card installed.
QuickStart Board, (#40000)
I will next do the C3 by itself, and with the Synapse memory board installed.
After that, I will do the Hydra.
Propeller .:.:--TACHYON--:.:. Forth V24150105.2330 VER: Propeller .:.:--TACHYON--:.:. Forth V24150105.2330 FREQ: 80MHZ (PLLEN OSCEN XTAL1 PLL16X) NAMES: $5B50...74B6 for 6,502 bytes (+4,073) CODE: $0924...3998 for 12,404 bytes (+8,087) CALLS: 405 vectors free RAM: 8,632 bytes free MODULES LOADED: 1A01: EXTEND.fth Tachyon Forth Propeller hardware debugger and explorer - 150109-1920 BOOT: EXTEND.boot BOOT: lshw FREQ: 80MHZ (PLLEN OSCEN XTAL1 PLL16X) PORT PINS +--------------------------------+ P00 inp L float || H inp P31 P01 inp L float || H out P30 P02 inp L float || up H inp P29 P03 inp L float || up H inp P28 P04 inp L float || down L inp P27 P05 inp L float || down L inp P26 P06 inp L float || up H inp P25 P07 inp L float || up H inp P24 P08 inp L down || float L inp P23 P09 inp L float || up H inp P22 P10 inp L float || down L inp P21 P11 inp L float || down L inp P20 P12 inp L float || float L inp P19 P13 inp L float || float L inp P18 P14 inp H up || float L inp P17 P15 inp L down || float L inp P16 +--------------------------------+ COG #0 registers $01F0: PAR = $0000_17E8 %0000_0000_0000_0000_0001_0111_1110_1000 $01F1: CNT = $102F_519E %0001_0000_0010_1111_0101_0001_1001_1110 $01F2: INA = $F340_5E00 %1111_0011_0100_0000_0101_1110_0000_0000 $01F3: INB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01F4: OUTA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000 $01F5: OUTB = $0000_0146 %0000_0000_0000_0000_0000_0001_0100_0110 $01F6: DIRA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000 $01F7: DIRB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01F8: CTRA = $0580_0000 %0000_0101_1000_0000_0000_0000_0000_0000 $01F9: CTRB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01FA: FRQA = $4000_0000 %0100_0000_0000_0000_0000_0000_0000_0000 $01FB: FRQB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01FC: PHSA = $8000_0000 %1000_0000_0000_0000_0000_0000_0000_0000 $01FD: PHSB = $0000_0000 %0000_0000_0000_0000_0000_0000_0000_0000 $01FE: VCFG = $2000_0000 %0010_0000_0000_0000_0000_0000_0000_0000 $01FF: VSCL = $0000_18F6 %0000_0000_0000_0000_0001_1000_1111_0110 Scanning I2C bus Fast I/O EXPANDER #1 at $42: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Fast 64K BOOT EEPROM at $A0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ----------------------------------------------------------------
I have the 1-Wire Tachyon code running and collecting 22 DS18B20 temperature sensors
every second (all of them).
So I was thinking.
If your port discovery shows a pull-up on a pin we could do a 1Wire-Reset to check if we get a
presence pulse and then do a 1-Wire discovery on this pin to find out what is there.
Maybe even map the tape codes to some meaningful names.
http://owfs.org/index.php?page=family-code-list
So does that mean you are volunteering to write this snippet of code to do this then?
Also, have a look at the latest EXTEND.fth as that has also added signature codes consisting of 6 longs at present sourced from the hardware scans. EEWORDS.fth has been updated to use variable sized blocks as I have set this to a default of 256 so that it only consumes 16K of EEPROM at present allowing the top 16K of a 64K device to be made available.
If I get this hardware detection down pat then it would be possible to load Tachyon onto any of the known boards and have it access the peripherals without any additional configuration.
Didn't check your pin discovery code details yet.
We could either store the bits for the pin pullup high while you do the scan.
Or I need to redo the scan to find those potential 1-Wire candidates.
What would you suggest?
<<< I will use SignIO - or actually PINLOAD? - that is fine.
Do any pins need to be excluded?
Like 28/29 30/31 ?
Can this do any harm to any device ?
(don't think so - it's just pulling a pulled up line down for a very short time).
Here you go:
1W.DISCOVER scans all pins (0..29) with a pull up for 1-wire devices and lists their IDs.
The first hex byte can be looked up here:
http://owfs.org/index.php?page=family-code-list
to identify the device.
( 1-Wire.fth ) { first part is base code from Peter Jakacki with minor adaptions second part is romsearch extensions by MJB Markus Baer } TACHYON [~ : 1WIRE.fth ." 1-wire interface 121025:0000 " ; { The 1-Wire interface is implemented in bytecode so it does not require a special cog to handle the timing. Testing is being done on DS1820+ and DS2450S+ chips. CHANGELOG: 121025 Fixed bugs in routines Added strong pullup after writing to provide power for parasitic devices Add some of Brian Riley's code Allow for redirection of DQ line } ( I/O DEFINITIONS ) LONG dq pri DQ@ dq @ ; pub DQ! dq ! ; #P14 |< DQ! \ set the default pub 1W.RESET ( -- ack ) DQ@ OUTCLR 1 ms DQ@ INPUTS #60 us DQ@ IN 0= #400 us ; pub 1W.BITWR ( iomask dat -- iomask dat/2 ) OVER OUTCLR \ pulse low for 1us SHROUT \ output next data bit then shift data right #60 us \ minimum cycle time OVER OUTSET \ Force line high at end of slot (rather than float) ; pub 1W.BITRD ( iomask dat -- iomask dat+ ) OVER OUTCLR OVER INPUTS \ pulse line low for 1us then float 8 us SHRINP \ assemble another bit by right shifting #50 us \ MJB OVER OUTSET \ Force line high at end of slot (rather than float) ; \ Transmit 8-bit lsb first pub 1W! ( dat -- ) DQ@ SWAP \ mask and data ( iomask dat ) 8 FOR 1W.BITWR NEXT \ write 8 bits lsb first 2DROP \ discard mask and used data ; \ Receive 8-bit data lsb first pub 1W@ ( -- dat ) DQ@ 0 \ initial mask and data ( iomask dat ) 8 FOR 1W.BITRD #45 us NEXT NIP #24 SHR \ right justify ( dat ) ; \ Get bytes from bus and print as hex bytes pub .1W ( bytes -- ) FOR 1W@ .BYTE SPACE NEXT ; pub READROM $33 1W! ; \ send read ROM command code pub SKIPROM $CC 1W! ; \ send skip ROM command code pub MATCHROM $55 1W! ; \ command to match an ID to a specific device pub CONVERTT $44 1W! ; \ commands all Temp sensors to start measurement (750 ms) pub READSCR $BE 1W! ; \ starts to: dumps 9 bytes (8 plus CRC) of device scratchpad pub 1WSCMD 1W.RESET DROP SKIPROM ; \ reset, skip ROM for single sensor only and prepare for next command pub RDROMH 1W.RESET DROP READROM 8 .1W ; \ read and print 8 byte ROM code pub RDSCRH 1WSCMD READSCR 9 .1W ; \ reset, skip ROM, read and print Scratchpad 9 bytes pub TEMP@ ( -- temp ) \ read first 2 bytes from scratchpad and assemble to temperature value on TOS ( binary, low nibble is fraction ) READSCR 1W@ 1W@ B>W \ combine 2 bytes to 1 long on stack ; pub .TEMP ( temp -- ) DUP $0F AND SWAP 4 SHR \ put whole degrees in one long and fraction in another $830A .NUM \ print whole number "." EMIT \ print decimal point #100 * 4 SHR \ turn binary bits to 100ths $020A .NUM \ print decimal ." 'C " ; \ 18B20 diagnostic routines : SHOWTEMP ( reads annd displays a single DS18B20 alone on a 1-W bus ) 1WSCMD CONVERTT #750 ms 1WSCMD TEMP@ DUP CR .TEMP SPACE 4 SHR 0 DO ." *" LOOP ; : SHOWSP ( reads annd displays a single DS18B20 SCRATCHPAD alone on a 1-W bus ) 1WSCMD CONVERTT #750 ms 1WSCMD RDSCRH ; \ : SHOWTEMPS BEGIN SHOWTEMP 2 seconds KEY? AND UNTIL ; : SHOWTEMPS BEGIN SHOWTEMP 2 seconds KEY UNTIL ; ]~ END { DEMO USAGE SHOWTEMPS +036.81'C ************************************ +036.62'C ************************************ +036.06'C ************************************ +035.68'C *********************************** +034.62'C ********************************** +034.68'C ********************************** +034.25'C ********************************** +033.31'C ********************************* +032.87'C ******************************** +032.50'C ******************************** +032.81'C ******************************** +033.12'C ********************************* +033.25'C ********************************* +033.31'C ********************************* +033.43'C ********************************* +033.50'C ********************************* +033.68'C ********************************* +033.68'C ********************************* +033.62'C ********************************* +032.87'C ******************************** +031.62'C ******************************* +031.00'C ******************************* +028.12'C **************************** +026.62'C ************************** +026.31'C ************************** +025.81'C ************************* +024.43'C ************************ +024.18'C ************************ +022.37'C ********************** +021.68'C ********************* +021.81'C ********************* +022.18'C ********************** +022.50'C ********************** +023.18'C *********************** +023.93'C *********************** } { To check the ROM of a single device: 1WRESET DROP READROM } ]~ END \ here starts the code by MJB Markus Baer ( 1WireMJB.fth ) TACHYON [~ : 1WIREMJB.fth ." 1-wire interface extensions MJB 140525:0000 " ; \ CREATE SMALL \ define SMALL before a load to specify a SMALL build to limit the sections included IFNDEF SMALL { \ DESCRIPTION \ \ Maxim 1-wire ROM Search algorithm \ straight forward implementation \ per AN937 "Book of iButton Standards", figure 5-3 \ for TACHYON Forth 2014 by Markus Baer aka MJB @ parallax forums, \ inspired by am-forth implementation by Bradford J. Rodriguez. \ USES \ 1WIRE.fth from Tachyon Forth by Peter Jakacki \ and of course the TACHYON System (Kernel 2.3 + EXTEND) - thanks Peter \ \ ** USES from 1-wire.fth **** \ 1W.RESET ( -- ack ) \ 1W.BITWR ( iomask dat -- iomask dat/2 ) \ 1W.BITRD ( iomask dat -- iomask dat+ ) \ 1W! ( c -- ) Write one byte to the 1-wire bus. \ 1W@ ( -- c ) Read one byte from the 1-wire bus. } { if you need it ... : 1W.!N ( xN .. x1 N -- ) FOR 1W! NEXT ; \ send N characters/bytes from stack : 1W.@N ( N -- x1 .. xN ) FOR 1W@ NEXT ; \ fetch N characters/bytes to stack : 1W..ROM RDROMH ; \ print 1Wire single device ROM code } BYTE 1W.lastdisc ( used as byte variable to hold last discrepancy ) BYTE 1W.doneflag BYTE 1W.rombit ( used as byte variable, 1..64 ) BYTE 1W.discmark \ buffer for one ROM-ID 1W.romid ( 8 byte array ) 8 BYTES 1W.romid pri 1W.!rombit ( f -- set the bit 1..32 given by 1W.rombit in buffer 1W.romid to flag value f ) 1W.rombit C@ 1- 8 U/MOD ( -- f bit# byte# ) 1W.romid + ( f bit# addr ) SWAP MASK SWAP ( f bitmask addr ) ROT ( bitmask addr f ) IF SET ELSE CLR THEN \ BIT! ; pri 1W.@rombit ( -- f \ f is 0 or non-0 not necc. 1 \ fetch the bit 1..32 given by 1W.rombit from buffer 1W.romid to flag f ) 1W.rombit C@ 1- 8 U/MOD ( -- bit# byte# ) 1W.romid + C@ ( -- bit# byte ) SWAP MASK ( -- byte bitmask ) AND ; \ helper pub <>0 ( val -- 0or1 \ convert any non 0 to 1 instead of -1 as 0<> does ) IF 1 ELSE 0 THEN ; #P14 |< DQ! \ for my setup MJB, this is the pin my 1-wire bus is attached to 4.7k or 5k pullup required \ single bit operations to read and write 1-wire bus pri 1W.BIT@ ( -- bit ) DQ@ 0 1W.BITRD NIP <>0 ; \ gives bit as 0 or 1 pri 1W.BIT! ( bit -- ) DQ@ SWAP 1W.BITWR 2DROP ; \ takes bit as 0 or 1 { for test pri .rombit ( bitnumber -- ) 1W.rombit C! 1W.@rombit . ; \ print 1W.rombit value pri .RB ( -- ) 1W.@rombit . ; pri .romid ( -- ) 1W.romid 8 ADO I C@ . SPACE LOOP ; } BYTE 1W.devcnt LONG 1W.devaddr pri 1W.NEWSEARCH ( -- \ clear variables used in search ) 1W.lastdisc C~ 1W.doneflag C~ 1 1W.rombit C! \ 1..64 1W.romid #8 ERASE 1W.devcnt C~ \ set device count to 0 ; pri 1W.SEARCHROM ( -- f ) ( search for one additional device. Returns 0 if done or 1 if more to come. see 1W.SCAN ) 0 ( default return value ) ( 0 ) 1W.doneflag C@ IF 1W.doneflag C~ \ clear doneflag EXIT ( leaves 0 ) THEN 1W.RESET IF ( presence signal detected? ) 1 1W.rombit C! ( yes: set ROM bit index to 1 ) 1W.discmark C~ ( set discrepancy marker to 0 ) ( 0 ) $F0 1W! ( send search command on bus ) ( 0 ) BEGIN 1W.BIT@ 1W.BIT@ 2* + ( 0 BA ) \ 2 bits A & B in bit pos 0 AND 1 DUP $03 = ( 0 BA flag ) IF ( bitA = bitB = 1?) DROP 1W.lastdisc C~ \ clear EXIT ( leaves 0 ) ELSE ( 0 BA ) ?DUP 0= ( 0 BA false | 0 true ) IF ( bitA = bitB = 0?) ( 0 ) 1W.rombit C@ 1W.lastdisc C@ = ( 0 flag ) IF 1 1W.!rombit ( 0 ) ELSE 1W.rombit C@ 1W.lastdisc C@ > ( 0 flag ) IF 0 1W.!rombit 1W.rombit C@ 1W.discmark C! ( 0 ) ELSE 1W.@rombit 0= ( 0 flag ) IF 1W.rombit C@ 1W.discmark C! ( 0 ) THEN THEN ( 0 ) THEN ( 0 ) ELSE ( 0 BA ) $01 AND ( bit A value , bit B is inverse so we don't need it ) 1W.!rombit ( 0 ) THEN THEN ( 0 ) 1W.@rombit <>0 \ gives 0 or 1 as logical values instead of 0 -1 1W.BIT! ( DROP what is this drop for ??? )( send ROM bit to bus ) 1W.rombit C@ 1+ DUP 1W.rombit C! ( 0 1W.rombitVal ) \ increment 1W.rombit index $40 > UNTIL \ check > 64 ( 0 ) 1W.discmark C@ DUP 1W.lastdisc C! ( 0 discmark ) 0= IF 1 1W.doneflag C! ( 0 ) ELSE 1+ ( set return value to 1 = true ) THEN ELSE ( no presence signal ) 1W.lastdisc C~ \ set 0 THEN ; \ calc the CRC given start and length of string/bytes. If string includes the CRC the result is 0 for OK pub CRC8 ( str cnt -- crc ) 0 ROT ROT ADO I C@ SWAP 8 FOR 2DUP XOR 1 AND ROT 2/ ROT 2/ ROT IF $8C XOR THEN NEXT NIP LOOP ; \ Demonstrates how to use SEARCHROM to find all attached devices and store them in table 1W.1Wdevs pri 1W.PRINTromid ( addr -- ) \ print the ROM-ID at address 8 ADO I C@ .BYTE SPACE LOOP CR ; TABLE 1W.1Wdevs #40 #8 * ALLOT \ prepare for 8 devices here, change as appropriate pub 1W.SCAN ( -- ) \ scan for any devices on 1-wire bus and store them in table 1W.1Wdevs CR 1 1W.NEWSEARCH 1W.1Wdevs 1W.devaddr ! \ begin at start of table CR BEGIN DUP .DEC ":" EMIT 2 SPACES 1+ 1W.SEARCHROM 1W.romid 1W.PRINTromid \ print it 1W.romid 8 CRC8 IF ." CRC mismatch above" CR THEN \ ' CMOVE ( src dst cnt -- ) Copy bytes from src to dst address for cnt bytes using increment for up or down 1W.romid 1W.devaddr @ 8 CMOVE \ SEARCHROM could be optimized to store directly to table, \ by making 1W.romid a CONST pointing to the table entry and changing it for each run 1W.devaddr DUP @ 8 + SWAP ! \ increment the address to store by 8 bytes 0= UNTIL CR ; { test it on 2 devices \ $3F00 INPUTS \ disable pins near my 1Wire for protection LAP 1W.SCAN LAP .LAP 28 09 6C CD 04 00 00 82 28 F7 E6 BF 04 00 00 3A Time: 56.01ms ok for discovering 2 DS18B20 sensors 1W.1Wdevs $20 DUMP 1W.1Wdevs $20 ADO I C@ .BYTE SPACE LOOP 1W.1Wdevs $16 ERASE } { some demo / test code pub 1W..1Wdevs \ print the table of 1W.1Wdevs discovered by 1W.SCAN ( if table is not full ) 1 1W.1Wdevs CR BEGIN \ BEGIN condition WHILE code REPEAT DUP C@ WHILE ( 1 1W.1Wdevs ) \ works only if there is at least one element in table which is 0ed SWAP DUP .BYTE ":" EMIT SPACE 1+ SWAP DUP 1W.PRINTromid 8 + REPEAT DROP ; pub 1W..1WdevsT \ print the table of 1W.1Wdevs discovered by 1w.scan in Table format for inclusion in Tachyon code 1W.1Wdevs CR ." TABLE 1W.my1Wdevs" CR BEGIN \ BEGIN condition WHILE code REPEAT DUP C@ WHILE ( 1 1W.1Wdevs ) SPACE DUP 8 ADO ." $" I C@ .BYTE ." | " LOOP CR \ ADO ( from cnt -- ) 8 + REPEAT DROP ; \ print the discovered 1Wire-IDs 1W..1Wdevs \ print the table of 1W.1Wdevs discovered by 1w.scan in Table format for inclusion in Tachyon code 1W..1WdevsT } \ 1 Wire Multibus CoMmanD takes the address of a ROM code and performs a matchROM command pub 1W.MCMD ( -- ) 1W.RESET DROP MATCHROM ; \ reset and send Match ROM command pub 1W.MATCH ( addr -- ) \ address sensor with 64-bit rom code given at addr then ready for next command 1W.MCMD 8 ADO I C@ 1W! LOOP ; \ IFNDEF SMALL \ DS18B20 diagnostic routines : 1W.SHOWTEMPM ( tableaddr n -- \ reads and displays a DS18B20 on a multibus. n is the index into the table of devices 1W.1Wdevs ) \ 1W.1Wdevs table of discovered 1W devices with SEARCHROM 1- 8 * + \ calculate start of ROM code to address DUP 1W.MATCH CONVERTT #750 ms \ 1W.MATCH TEMP@ DUP .TEMP 1W.MATCH TEMP@ .TEMP \ SPACE 4 SHR 0 DO ." *" LOOP \ bar graph ; : 1W.SHOWSPM ( tableaddr n -- \ reads and displays a DS18B20 SCRATCHPAD on a multibus n is the index into the table of devices 1W.1Wdevs ) \ 1W.1Wdevs table of discovered 1W devices with SEARCHROM 1- 8 * + \ calculate start of ROM code to address DUP 1W.MCMD CONVERTT #750 ms 1W.MCMD RDSCRH ; \ for sensor# from I = 1 to n from ROM-Code table given show the temp readings cyclically until key pressed : 1W.SHOWTEMPSM ( tableaddr n -- ) CR BEGIN 1 OVER ADO \ from 1 to n OVER I 1W.SHOWTEMPM SPACE LOOP CR 2 seconds \ KEY? AND \ AND required, since KEY? ( -- key flag ) KEY UNTIL 2DROP ; } \ end IFNDEF SMALL { the generated table ready to paste into Tachyon again TABLE 1W.my1Wdevs $28 | $09 | $6C | $CD | $04 | $00 | $00 | $82 | $28 | $F7 | $E6 | $BF | $04 | $00 | $00 | $3A | 1W.my1Wdevs 2 1W.SHOWTEMPSM \ show the temperature for my 2 sensors \ next line works directly after romsearch from found IDs \ 1W.1Wdevs 2 1W.SHOWTEMPSM 1W.1Wdevs 2 1W.SHOWTEMPSM +023.00'C +023.18'C +023.00'C +023.18'C +023.31'C +023.18'C +024.00'C +023.18'C +024.50'C +023.18'C +025.00'C +023.18'C +025.37'C +023.18'C +025.81'C +023.18'C +026.12'C +023.18'C +026.18'C +023.25'C +026.25'C +023.75'C +026.06'C +024.18'C +025.87'C +024.62'C +025.75'C +025.06'C +025.62'C +025.31'C ok 1W.1Wdevs 1 1W.SHOWTEMPSM : bb 1W.SCAN 1W.1Wdevs SWAP 1W.SHOWTEMPSM ; : bbb 1 bb ; \ Temp measurement GUI pub TEMPGUI ( nSensors -- ) VCLS 1+ BEGIN HOME DUP 1 DO ERLINE I .DEC SPACE 1W.1Wdevs I 1W.SHOWTEMPM CR LOOP \ KEY? AND \ AND required, since KEY? ( -- key flag ) KEY UNTIL 2DROP ; #22 TEMPGUI pub TEMPGUI2 ( nSensors -- ) VCLS 1+ BEGIN HOME DUP 1 DO 1W.1Wdevs I 1- 8 * + \ calculate start of ROM code to address 1W.MATCH CONVERTT LOOP #750 ms DUP 1 DO ERLINE I .DEC SPACE 1W.1Wdevs I 1- 8 * + 1W.MATCH TEMP@ .TEMP CR LOOP \ KEY? AND \ AND required, since KEY? ( -- key flag ) KEY UNTIL 2DROP ; #22 TEMPGUI2 BEGIN "-" ECHO KEY .S UNTIL } { HELP new 1-Wire scan on pins with pull up resistor and report } pub 1W.DISCOVER \ ." 1-Wire pin scan" CR 0 #30 ADO I PINLOAD? "U" = IF I MASK DQ! 1W.RESET IF ." 1-Wire Devices on PIN" I .DEC 1W.SCAN CR THEN THEN LOOP ; \ 1W.DISCOVER ]~ END
Here my 22 DS18B20 Temperature Sensors on Pin 14
1W.DISCOVER 1-Wire Devices on PIN0014 0001: 28 60 4C BF 04 00 00 80 0002: 28 F0 69 CD 04 00 00 B4 0003: 28 88 45 CE 04 00 00 DC 0004: 28 78 6D CD 04 00 00 E0 0005: 28 B4 94 CE 04 00 00 DF 0006: 28 5C 43 CE 04 00 00 58 0007: 28 F2 62 CD 04 00 00 AA 0008: 28 F2 57 6F 06 00 00 1D 0009: 28 1A 42 BF 04 00 00 75 0010: 28 06 60 77 06 00 00 42 0011: 28 86 0E CE 04 00 00 56 0012: 28 B6 50 CE 04 00 00 8C 0013: 28 0E 30 CE 04 00 00 3B 0014: 28 CE FC CD 04 00 00 2F 0015: 28 61 98 CE 04 00 00 D1 0016: 28 B1 29 CE 04 00 00 97 0017: 28 29 4A CE 04 00 00 D8 0018: 28 E9 78 6F 06 00 00 29 0019: 28 ED 61 70 06 00 00 D8 0020: 28 3D E6 6F 06 00 00 24 0021: 28 4F 68 6E 06 00 00 34 0022: 28 4F D3 CD 04 00 00 65
I think you are about to bring me Kicking and screaming into learning another new language. My very first programming experience was writing ASM routines in Z80 ASM back 30 some years ago. I was self taught reading and trying lots of OP's code and single stepping code through a debugger. Right now I have an ESP8266 to test that I am not sure is working, and another to test that is still in its original package. I also have been struggling with Getting some WS2812's to behave the way I want them to. ie I have 5 of them on a single port and I want to control the color of each one of them individually. can Tachyon easily interface with a PASM routine running in another cog like using jonnymac's ws2812 driver and providing the high level code?
My problem has been one of time to play with code. I work a full time job with two hours of commute each day. So when I am home my wife, who works at home alone, wants to socialize with me.
I will have some computer time this afternoon so will download your hardware debugger and give it a spin.
Jim
Well I "brung" myself up on SC/MP. 2650, 8080, 9900, Z80, 8085, 8051, 6502s, and many many others and mostly in machine code or if I was lucky, an assembler. But when you are done kicking and screaming trying to find out what's wrong with your hardware or your code then the Hardware Explorer is really a quick way to check out your Prop and hardware without having to learn another language. The fact that you can combine "commands" to get it do something more is a bonus and if from there a person stops fighting their preconceptions and accepts that the "language" (or perhaps culture) is different, that it is not C or Spin, then they can start having some fun and being productive.
Do you know that if you connect your WS2812s to a pin that you only need to type a few words to communicate to an array of these? No need to load any "driver", it's just a few lines of code that I wrote as a simple module that's built into the kernel. For a more complete example of interacting with these LEDs, changing patterns and colors while it's operating, have a look at this source document. Just copy and paste the whole document into an editor, modify your user parameters near the start, and then copy and paste that into your board and play from there. Those couple of initial steps might only take seconds and you can run some quick demos that are built-in like DEMO or CHASE or SLIDE or MATRIX or MAINFRAME along with varying speed, brightness, color, patterns etc.
If your commute was on public transport you could even use your phone or tablet with a USB to serial cable and a terminal app and talk to your Prop and LEDs as well as power them as this is something that I have done (not on public transport). Imagine having the LEDs strapped to your chest while you are talking to them from your phone! on public transport! OMG, he's got a b*mb!
Jim
6 hours a day! Yikes! But think of all the "non-socializing" Propeller time you could have!
2 hours commute per day !
Please, I want you to stop and think about that. If you sleep 8 hours per day and work 8 hours per day then you have 8 hours left for yourself. That is to say only one third of your allotted life span is actually yours.
If you then spend 2 hours per day commuting that is eating 25 percent of your life! (OK I'm ignoring weekends, but you are probably too tired to enjoy those anyway.)
That is 25 percent of your life that you could be spending with family and friends or just tinkering with your own ideas.
If you look at it that way you must see how crazy that is. It's like having your life shortened from 70 odd years to only 50 or so. Who would want that?
I did that as well for some years, it all made sense at the time, the money was good and the work was interesting. Looking back I really regret it as a big waste of life. I burned myself out.
For goodness sake. Move closer to work. Get a different job. Save yourself!
Sorry to be so up front and personal about this. I just don't want anyone to end up feeling like I do if they can possibly help it.
I am hoping for a little spare time to try this finally.
Can you post (or email) me the source files and what I need to compile this please?
I need to recompile for 6.5MHz as that is my usual xtal in my boards and it makes it easier for me to try when I have a few spare minutes
Thanks, Ray