New BASIC compiler for Prop1 and Prop2

1235713

Comments

  • Thanks for testing it Ray. It sounds like I need to find a newer version of propeller-load that can handle WiFi.
  • ersmith wrote: »
    Thanks for testing it Ray. It sounds like I need to find a newer version of propeller-load that can handle WiFi.
    proploader knows how to do wifi downloads. However, it doesn't handle XMM programs. I suspect that won't be a problem for you though.

  • Below is a test program where I am trying to use the familiar high() and low() commands. The program compiles without any errors, but there is no flashing of the LED on pin 26.

    If Eric does not mind, I am calling this BASIC, pBas or pBAS.

    Will pBas provide an #include provision? I am thinking that, as an example, the high, low, and pausems commands could be placed in a lib, so you only code it once, and have it called within your program.

    Ray
    rem test2.bas
    
    let mscycles = clkfreq / 1000
    
    '*******************************
    'Main
    print "This is the test2.bas program"
    
    do
    	high 26
    	pausems 500
    	low 26
    	pausems 26
    loop
    
    '*******************************
    sub high(pin)
    	dim pin%
    	direction(pin) = output
    end sub
    
    sub low(pin)
    	dim pin%
    	direction(pin) = input
    end sub
    
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
  • Rsadeika wrote: »
    Below is a test program where I am trying to use the familiar high() and low() commands. The program compiles without any errors, but there is no flashing of the LED on pin 26.

    The second pausems is for only 26 ms. Is that what you intended?
    Also, your high() and low() functions are changing the direction, not the output value. They really should be something like:
    sub high(pin)
      output(pin) = 1
    end sub
    sub low(pin)
      output(pin) = 0
    end sub
    
    And then in your main code do
      direction(pin) = output
    
    once to set the pin as an output.
    If Eric does not mind, I am calling this BASIC, pBas or pBAS.
    Probably "fBas" would be a better abbreviation, to avoid confusion with PropBasic.
    Will pBas provide an #include provision?
    It already does, actually. I need to write documentation for the preprocessor, but it supports #include, #define, #ifdef, #elseifdef, and #endif.

    Besides #include (which just literally includes one file into another) there is also "class using filename", which lets you include files as objects, similar to the OBJ statement in Spin. "class using" works with both Spin and BASIC files.

    Eric
  • David Betz wrote: »
    ersmith wrote: »
    Thanks for testing it Ray. It sounds like I need to find a newer version of propeller-load that can handle WiFi.
    proploader knows how to do wifi downloads. However, it doesn't handle XMM programs. I suspect that won't be a problem for you though.

    Thanks David! I'll switch to proploader for the next version.

  • I get a compile error. I tried adding 'dim pin%', but that did not work.

    Ray
    rem test2.bas
    
    let mscycles = clkfreq / 1000
    
    direction(pin) = output
    '*******************************
    'Main
    print "This is the test2.bas program"
    
    do
    	high 26
    	pausems 500
    	low 26
    	pausems 500
    loop
    
    '*******************************
    sub high(pin)
    	
    	output(pin) = 1
    end sub
    
    sub low(pin)
    	
    	output(pin) = 0
    end sub
    
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    
    G:/fastspin/spin2gui/bin/fastspin -l -O1 -L ./lib G:/fastspin/programs/test2/test2.bas
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2018 Total Spectrum Software Inc.
    Version 3.9.5-beta Compiled on: Oct 11 2018
    test2.bas
    G:/fastspin/programs/test2/test2.bas(5) error: Unknown symbol pin
    child process exited abnormally
  • ersmith wrote: »
    David Betz wrote: »
    ersmith wrote: »
    Thanks for testing it Ray. It sounds like I need to find a newer version of propeller-load that can handle WiFi.
    proploader knows how to do wifi downloads. However, it doesn't handle XMM programs. I suspect that won't be a problem for you though.

    Thanks David! I'll switch to proploader for the next version.
    proploader defaults to trying to do a wifi load. You have to specify -s on the command line to get it to do serial loads. In retrospect, that might not have been the best default but proploader was written for the WX wifi module originally and later expanded to include serial support.
  • Rsadeika wrote: »
    I get a compile error. I tried adding 'dim pin%', but that did not work.

    Use "direction(26) = output". Or you could add
    const ledpin = 26
    
    at the beginning of your code so that it's easy to change the pin. For example:
    rem blinker: blink an led
    
    const ledpin = 16
    
    ' set the led pin as an output
    direction(ledpin) = output
    
    print "This is the LED blink test program"
    
    ' loop blinking the led
    do
      high ledpin
      pausems 500
      low ledpin
      pausems 500
    loop
    
    sub high(pin)
      output(pin) = 1
    end sub
    
    sub low(pin)
      output(pin) = 0
    end sub
    

    The most recent version of fastspin has pausems as a builtin function so you probably don't need to define that, but your definition looked OK and you can use it if you like

    Also note that 'dim pin%' declares a variable called 'pin%' and is different from 'dim pin'. I think that may be an area where fastspin differs from qbasic and freebasic.

    Eric
  • I was trying to get around the use of 'const ' . The way it is now, you have to pre-define the pins that you will be using. In some ways this is like working with spin, where you deal with the pin defs up front. I was thinking along the lines of PropGCC, where you have pre-definitions under the hood, so all you do is high(26) or low(26), and it works.

    I am liking the spin2gui program, although some improvements would be nice. One would be, a Load command, where it writes the program to the EEPROM. The other is, you do not have any support for .bas in terms of creating a or saving a .bas file.

    Ray
  • Rsadeika wrote: »
    I was trying to get around the use of 'const ' . The way it is now, you have to pre-define the pins that you will be using. In some ways this is like working with spin, where you deal with the pin defs up front. I was thinking along the lines of PropGCC, where you have pre-definitions under the hood, so all you do is high(26) or low(26), and it works.
    Well, you could put a 'direction(pin) = output' line in both high() and low(), before setting the value of output(pin). I think that may be what the PropGCC functions do. It's a little less efficient, because it means you're constantly setting the direction when it's only necessary to set it once.
    I am liking the spin2gui program, although some improvements would be nice. One would be, a Load command, where it writes the program to the EEPROM. The other is, you do not have any support for .bas in terms of creating a or saving a .bas file.
    Thanks for the suggestions!
  • The program below compiles and runs as expected. The next program, I will try to have pin 27 LED blinking in the Main, and I will try to get pin 26 LED to blink in a cpu(COG).

    I noticed that pBas does not have any break or exit commands. What would be the method for getting out of a while loop.

    Ray

    rem test2.bas
    ' October 12, 2018
    ' General use of pBas compiler
    
    ' Define clock freq
    let mscycles = clkfreq / 1000
    ' Variables
    dim pin
    '*** Subs & Functions ***
    sub high(pin)
    	direction(pin) = output
    	output(pin) = 1   ' LED is on
    end sub
    
    sub low(pin)
    	direction(pin) = output
    	output(pin) = 0   ' LED is off
    end sub
    
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    '*******************************
    'Main
    print "This is the test2.bas program"
    
    do
    	high 27   ' Pin 27 on
    	pausems 500
    	low 27    ' Pin 27 off
    	pausems 500
    loop
    
    '*******************************
    
  • The program below compiles and runs as expected. Not sure as to how to use the stack, I dim it one size and the usage is of a different size, but it works.

    Does, or will, pBas have inline pasm? I am wondering as to the best way for pBas to utilize all the Spin driver code that is available. I think JonnyMac had written quite a few drivers in pasm, but there also is quite a few drivers that are written in Spin. One large driver, that could be of great use, is the SD driver, which is in Spin.

    Since Parallax has the Activity Board WX, and the FLiP module, maybe there should be an effort made to start trying to create some usage of the different items for the these platforms. For the Activity Board WX: the SD, WiFi, ADC, sound, motor driver, …, etc. Other items of interest could be the RTC, Temp/humidity module and others.

    Ray
    rem test3.bas
    ' October 12, 2018
    ' pBas cpu(COG) usage.
    
    ' Are these declarations all Global?
    ' Define clock freq
    let mscycles = clkfreq / 1000
    ' Variables
    dim pin
    '*** Subs & Functions ***
    sub high(pin)
    	direction(pin) = output
    	output(pin) = 1   ' LED is on
    end sub
    
    sub low(pin)
    	direction(pin) = output
    	output(pin) = 0   ' LED is off
    end sub
    
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    '*******************************
    'Main
    dim stack(4) 'This is the minimal to run the cpu job1
    ' Start the cpu(COG)
    var a = cpu(job1(26), @stack(1)) ' Not sure what size @stack(1) is
    
    do
    	high 27   ' Pin 27 on
    	pausems 500
    	low 27    ' Pin 27 off
    	pausems 500
    loop
    
    '*******************************
    ' This is the cpu(COG) job.
    sub job1(pin)
    	do
    		high pin   ' Pin 27 on
    		pausems 300
    		low pin    ' Pin 27 off
    		pausems 300
    	loop
    end sub
    '*******************************
    
  • Rsadeika wrote: »
    I noticed that pBas does not have any break or exit commands. What would be the method for getting out of a while loop.

    The usual way would be to have the while loop test for a variable, and to set that inside the loop. For example, an (ugly) way to print some integers is:
    var done = 0 ' indicates loop is finished
    var i = 1
    do
      print i
      i = i + 1
      if (i > 4) done = 1
      print "still looping"
    loop until done <> 0
    
    You could also use a goto:
    var i = 1
    do
      print i
      i = i + 1
      if (i > 4) goto out
      print "still looping"
    loop
    out:
    
  • Rsadeika wrote: »
    The program below compiles and runs as expected. Not sure as to how to use the stack, I dim it one size and the usage is of a different size, but it works.
    The @stack(1) just returns a pointer to the first element of the stack array (remember that in fastspin BASIC array indices start at 1, not 0).
    Does, or will, pBas have inline pasm? I am wondering as to the best way for pBas to utilize all the Spin driver code that is available.
    fastspin supports inline assembly between "asm" and "endasm". But if you want to use Spin, you can import it directly with "class using". (The compiler is called "fastspin" after all, and that was the first language it supported -- the BASIC is a new addon!)

    For example, to use the FullDuplexSerial.spin driver from a BASIC program you can do:
    ' create a FullDuplexSerial object named fds
    ' this is just like the Spin command OBJ fds : "FullDuplexSerial.spin"
    
    dim fds as class using "FullDuplexSerial.spin"
    
    ' initialize the fds object
    ' WARNING: we're choosing to use pins 31 and 30 here, which
    ' will conflict with the built-in print commands. Don't try to
    ' use print after the fds.start. If we used other pins (to communicate
    ' with some device, for example) then this wouldn't be an issue
    
    fds.start(31, 30, 0, 115_200)
    do
      fds.str("hello, world!")
      fds.tx(13)
      fds.tx(10)
    loop
    

    "class using" accepts either a BASIC or Spin file.

  • I think I read somewhere that pBas will be able to be used with the P2 chip. I also think I read that pBas, at the moment is set up to run in LMM. What is available now is COG Ram, HUB Ram, and for the P2, HUB Execute. How will pBas be able to use these specific Ram areas? Will you have something like a setting in pBas:
    TMM = Cog Ram
    LMM = Hub Ram
    XMM = P2 Hub Execute

    Ray
  • fastspin defaults to hubexec in P2 mode (if the -2 switch is given) and LMM in P1 mode. If you use the --code=cog option then it will compile the code to run in COG memory in both cases.
  • Rsadeika wrote: »
    I think I read somewhere that pBas will be able to be used with the P2 chip. I also think I read that pBas, at the moment is set up to run in LMM. What is available now is COG Ram, HUB Ram, and for the P2, HUB Execute. How will pBas be able to use these specific Ram areas? Will you have something like a setting in pBas:
    TMM = Cog Ram
    LMM = Hub Ram
    XMM = P2 Hub Execute

    Ray


    Ahem....'t ain't called "pBas", it's called fastspin(BASIC).

    Other readers are going to be confused 😕

    Failure is not an option...it's bundled with the software.
  • OK fastspin(BASIC), it is, until Eric gives it an official name.

    Since I have a WX Activity Board with DS1302 module installed, I thought I would try doing a real use program with fastspin(BASIC).

    The program below compiles without complaints, but the value is showing up as 0, it should be 13, todays date. I believe that in the Spin program, the value(s) is presented as a byte. So, I am not sure if fastspin(BASIC) is doing a correct print of the day1 variable. Have not done anything in Spin, in the last ten years, so I could be wrong with my interpretation.

    I attached the DS1302.spin program, for easy referencing.

    Ray

    test_rtc.bas
    rem test_rtc.bas
    ' October 13, 2018
    ' Test of the RTC on the WX Activity Board
    
    dim rtc as class using "DS1302_full.spin"
    
    let mscycles = clkfreq / 1000
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    dim day1 as byte
    dim month1 as byte
    dim year1 as byte
    dim dow1 as byte
    dim day
    dim month
    dim year
    dim dow
    
    rtc.init(10,11,9)
    
    rtc.readDate(day1, month1, year1, dow1)
    
    'day1 = day
    
    do
    	print "day", day1
    	pausems 3000
    loop
    
    
    ds1302_full.spin
    {{ DS1302_full.spin
    ┌─────────────────────────────────────┬────────────────┬─────────────────────┬───────────────┐
    │ DS1302 driver v1.3                  │ BR             │ (C)2010             │  8Jul2010     │
    ├─────────────────────────────────────┴────────────────┴─────────────────────┴───────────────┤
    │                                                                                            │
    │ A full-featured DS1302 timekeeping chip driver.  Based on the original object by           │
    │ Daniel Robert.                                                                             │
    │                                                                                            │
    │ Notes:                                                                                     │
    │ •Original object here: http://obex.parallax.com/objects/89/                                │
    │ •12 hour mode is not supported in this object.  The reason is that it would add            │
    │  significant complexity to this object for minimal benefit.  A better solution is          │
    │  to handle the 12/24 hour conversion in software outside of this object if needed.         │
    │  Okay.  So it is nearly full-featured.                                                     │
    │ •The DS1302 data sheet specs the maximum frequency on the clk pin as:                      │
    │  0.5MHz@2V, 2MHz@5V --> 1.5MHz@3.3V (1.5 uS per clock, 120 ticks@clkfreq=80MHz)            │
    │  Original object had a 2 uS pause between clock pin transitions.  However, it seems to     │
    │  work fine with no wait @ clkfreq=80MHz...apparently spin can't outrun the DS1302.         │
    │  Not tested at clkfreq=100MHz.                                                             │
    │ •Experimented with trickle charger using 1 diode+2K resistor setting. 10µF                 │
    │  electrolytic cap kept DS1302 powered up for >10 minutes. Implies a 1000µF should be good  │
    │  for ~16 hrs of backup power...enough to last through a typical brown-out or black-out     │
    │  (if leakage current and wide tolerance band of electrolytics doesn't kill it first)       │
    │ •Note that this device needs to have a 32.768KHz crystal with 6pF capacitance in order to  │
    │  keep accurate time: http://forums.parallax.com/forums/default.aspx?f=25&m=467246          │
    │                                                                                            │
    │ See end of file for terms of use.                                                          │
    └────────────────────────────────────────────────────────────────────────────────────────────┘
    DEVICE PINOUT & REFERENCE CIRCUIT
                          ┌────┐               1000µF
                   3.3V │      │ backup_Vin  ── to gnd
       xtal          xi │DS1302│ clk         ─── to prop pin
       32.768 KHz    xo │      │ io          ─ 1KΩ resistor to prop pin
                        ┌│      │ ce          ─── to prop pin
                    GND  └──────┘      
    
    
    TRICKLE CHARGER NOTES
    'Trickle charger setup     tc_enable     diodeSel    resistSel
    '                              |            |          |
    ' write(command(clock,tc,w),(%1010 << 4) + (2 << 2)+ ( 3 ))
    
    Diode select register bits:  00 = trickle charger disabled
                                 01 = 1 diode enabled
                                 10 = 2 diodes connected in series (more voltage drop when in charging mode)
                                 11 = trickle charger disabled
    
    Resistor select bits:        00 = no resistor   0Ω
                                 01 = R1            2KΩ
                                 10 = R2            4KΩ
                                 11 = R3            8KΩ
    
    'Examples of other useful config and control commands
    'write(command(clock,sec,w),read(command(clock,sec,r))&%1000_0000)      'set clock halt bit
    'write(command(clock,ctrl,w),%1000_0000)                                'set write-protect bit
    'write(command(clock,hr,w),read(command(clock,hr,r))&%1000_0000)        'set 12h mode
    
    V1.1 - 27Oct09 fixed mis-labeled pins in docs (clk and io were swapped in 1.0)
    V1.2 - 28Mar10 fixed bug in config method that caused seconds to be reset (thanks, Doug!)
    v1.3 - 26Jun10 cleanup and additional documentation
    
    }}
    CON
    'command byte options   
      #0, clock,ram
      #0, sec, mi, hr, day, mo, dow, yr, ctrl, tc, #31, burst
      #0, w,r
    
      
    VAR
      byte clk                                   'clock
      byte io                                    'data io
      byte ce                                    'chip enable
      byte datar
    
    
    PUB command(clock_or_ram, register, r_or_w)
    ''Returns a DS1302 command byte
    ''clock_or_ram : select clock or ram (allowed values: clock, ram)
    ''register     : register name (allowed values: 0-30, sec, mi, hr, day, mo, dow, yr, ctrl, tc, burst)
    ''r_or_w       : read or write (allowed values: w, r)
    ''Usage        : cmd:=command(rtc#ram, 21, rtc#w)        --> write to RAM byte 21
    ''               cmd:=command(rtc#clock, rtc#min, rtc#r) --> read minute register
    
      return (1<<7) + (clock_or_ram<<6) + (register<<1) + r_or_w
    
    
    PUB init( inClk, inIo, inCe ) 
    ''Initialize propeller serial com channel with DS1302.  Call once after prop power-up.
    ''Usage: rtc.init(clk_pin, io_pin, chipEnable_pin)
    
      clk := inClk                               'save pin numbers
      io  := inIo
      ce  := inCe
    
      dira[ce]~~                                 'configure chip enable pin
      outa[ce]~            
      dira[clk]~~                                'configure clock pin
      outa[clk]~           
      
    
    PUB config
    ''Config DS1302.  Call once after DS1302 power-up.
    ''Usage: rtc.config
    
      write(command(clock,ctrl,w),0)                                        'clear write-protect bit
      write(command(clock,sec,w),read(command(clock,sec,r)) & %0111_1111)   'clear halt bit
      write(command(clock,hr,w),read(command(clock,hr,r)) & %0111_1111)     'set 24hr mode
      write(command(clock,tc,w),0)                                          'disable trickle charger
    
    
    PUB setDatetime( _mth, _day, _year, _dow, _hr, _min, _sec )
    ''Set date and time
    
      write($8c, bin2bcd( _year ) )
      write($8a, _dow )
      write($88, bin2bcd( _mth ) )
      write($86, bin2bcd( _day ) )
      write($84, bin2bcd( _hr ) )
      write($82, bin2bcd( _min ) )
      write($80, bin2bcd( _sec ) )
    
    
    PUB readDate( _day, _mth, _year, _dow )
    ''Read current date (day, month, year, day-of-week)
    ''Usage: rtc.readDate( @day, @month, @year, @dow )
    
      byte[_year] := bcd2bin( read($8d) )
      byte[_mth] :=  bcd2bin( read($89) )
      byte[_day] :=  bcd2bin( read($87) )
      byte[_dow] :=  bcd2bin( read($8b) )
    
      
    PUB readTime( _hr, _min, _sec ) | tmp1, tmp2
    ''Read current hour, minute, second
    ''Usage: rtc.readTime( @hour, @minute, @second )
    
      byte[_hr]  := bcd2bin( read($85) )
      byte[_min] := bcd2bin( read($83) )
      byte[_sec] := bcd2bin( read($81) )
    
      
    Pub read( cmd ) | i
    ''Read a byte of data per command byte
    
      outa[ce]~~           
      writeByte( cmd )
      dira[io]~             'set to input
      readByte
      outa[ce]~            
      return(datar)
    
    
    Pub write( cmd, data ) 
    ''Write a byte of data per cmd byte
    
      outa[ce]~~           
      writeByte( cmd )
      writeByte( data )
      outa[ce]~            
    
    
    PUB writeN(cmd, dataPtr, n)|i
    ''Write a stream of n bytes from byte array pointed to by dataPtr
    
      outa[ce]~~           
      writeByte( cmd )
      repeat i from 0 to n
        writeByte(byte[dataPtr][i])
      outa[ce]~            
      
    
    Pub readN(cmd, dataPtr, n)|i
    ''Read a stream of n bytes of data and put in byte array pointed
    ''to by dataPtr
    
      outa[ce]~~           
      writeByte( cmd )
      dira[io]~             'set to input
      repeat i from 0 to n
        readByte
        byte[dataPtr][i]:=datar
      outa[ce]~            
     
    
    PRI readByte|i
    
      datar~                           
      repeat i from 0 to 7          
         if ina[io] == 1
          datar |= |< i     ' set bit
        outa[clk]~~          
        outa[clk]~           
    
    
    PRI writeByte( cmd ) | i  
    
      dira[io]~~              'set to output 
      repeat i from 0 to 7    
        outa[io] := cmd       
        outa[clk]~~          
        cmd >>= 1
        outa[clk]~           
    
    PRI bin2bcd(dataIn) | tmp
    'Convert a byte of binary data to binary coded decimal
    
      tmp:= dataIn/10
      result := dataIn - ( tmp * 10 ) + ( tmp << 4 )
    
    
    PRI bcd2bin(dataIn)
    'Convert a byte of binary coded decimal data to binary
    
      result := (dataIn & %00001111) +  ((dataIn >> 4) & %00001111)*10
    
    
    DAT
    
    {{
    
    ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │                                     TERMS OF USE: MIT License                                       │                                                            
    ├─────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and    │
    │associated documentation files (the "Software"), to deal in the Software without restriction,        │
    │including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,│
    │and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,│
    │subject to the following conditions:                                                                 │
    │                                                                                                     │                        │
    │The above copyright notice and this permission notice shall be included in all copies or substantial │
    │portions of the Software.                                                                            │
    │                                                                                                     │                        │
    │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT│
    │LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  │
    │IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         │
    │LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION│
    │WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                      │
    └─────────────────────────────────────────────────────────────────────────────────────────────────────┘
    }} 
    
  • Ray:

    You're right that the day, month, year, etc. have to be bytes. You missed the comment in the Spin file that the readDate and readTime functions want the addresses of the bytes:
    ''Usage: rtc.readDate( @day, @month, @year, @dow )
    
    so if you change the line in your BASIC program from
    rtc.readDate(day1, month1, year1, dow1)
    
    to
    rtc.readDate(@day1, @month1, @year1, @dow1)
    
    then it may work. (I don't have hardware to test it myself.)

  • Adding the "@" did the trick, now the program runs as expected. This fastspin(BASIC) is starting to really grow on me.

    I also did a program code size comparison, fastspin(BASIC) - 6616; SimpleIDE PropGCC - 6576. The PropGCC version was derived from DS1302_full.spin.

    The next thing that I will try is CM2302 module, the Spin code for that looks a little more confusing. It works best with float variables, which fastspin(BASIC) can handle.

    The next thing up would be to write the date/time and the temp/humidity to the SD card. But, I noticed that the open command and some sort of read/write to the SD card or file, are not available. So, this just might have to wait.

    Ray
    rem test_rtc.bas
    ' October 13, 2018
    ' Test of the RTC on the WX Activity Board
    
    dim rtc as class using "DS1302_full.spin"
    
    let mscycles = clkfreq / 1000
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    dim day1 as byte
    dim month1 as byte
    dim year1 as byte
    dim dow1 as byte
    dim minutes as byte
    dim hour as byte
    dim seconds as byte
    dim dow
    
    rtc.init(10,11,9)
    
    
    do
    	rtc.readDate(@day1, @month1, @year1, @dow1)
    	rtc.readTime(@hour,@minutes,@seconds)	
    	print month1;"/";day1;"/";"20";year1;"  ";hour;":";minutes;":";seconds
    	pausems 3000
    loop
    
  • This is really exciting. I had no idea that we were at the stage of interfacing to existing objects....watching with great anticipation 👍😎
    Failure is not an option...it's bundled with the software.
  • This one is a little more confusing. I think the DHTnn_Object.spin starts a COG, so I am not sure what happens within fastspin(BASIC). I think the starting of the COG is essential for the program to show the correct results. Right now the test_temp.bas compiles and runs, but it is showing 0.000 for the temp. Not sure what is going on.

    Yep, fastspin(BASIC) ROCKS!

    Ray

    test_temp.bas
    rem test_temp.bas
    ' October 13, 2018
    ' Test of the CM2302 module on the WX Activity Board
    
    dim cm2302 as class using "DHTnn_Object.spin"
    'dim f as class using "FloatMath.spin"
    'dim fp as class using "FloatString.spin"
    
    let mscycles = clkfreq / 1000
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    dim temp#,humid#,misc#
    
    
    cm2302.StartDHTnn(8,22,@temp#,@humid#,@misc#)
    
    do
    
    print "Temp ";temp#
    pausems 3000
    loop
    
    DHTnn_Object.spin
    ''******************************************
    ''*  Title: DHTnn_Object                   *
    ''*  Modified from DHT21_Object -          *
    ''*  Walter T. Mosscrop 2016               *
    ''*  Original Author: Gregg Erickson  2012 *
    ''*  See MIT License for Related Copyright *
    ''*  See end of file and objects for .     *
    ''*  related copyrights and terms of use   *
    ''*  This object draws upon code from other*
    ''*  OBEX objects such as servoinput.spin  *
    ''*  and DHT C++  from Adafruit Industries *
    ''*                                        *
    ''*  This object reads the temperature and *
    ''*  humidity from an DHT11 or DHT22       *
    ''*  using a unique 1-wire serial protocol *
    ''*  with 5 byte packets where 0s are 26uS *
    ''*  long and 1s are 70uS.                 *
    ''*                                        *
    ''*  The object automatically returns the  *
    ''*  temperature and humidiy to variables  *
    ''*  memory every few seconds as Deg C and *
    ''*  relative percent respectively. It also*
    ''*  return an error byte where true means *
    ''*  the data received had correct parity  *
    ''*                                        *
    ''*  The read loop has been reworked to    *
    ''*  stabilize the timing and reduce the   *
    ''*  number of invalid reads due to timing *
    ''*  issues                                *
    ''******************************************
    {
       Vcc──────────────Red (Power)
                    │
                   10K (Pull-Up Resistor)
                    │
       Prop Pin ────────Yellow (Data)
    
    
       VSS──────────────Black (Ground)
    
    }
    CON
    
      MAX_SAMPLES = 40 ' 40 one-bit samples 
    
    VAR
    
    long APin,Device                  
    long MeasurementStack[50]
    long clkpermicro, clkminpulse
    long measurementCog, measuring
    long MeasurementValues[MAX_SAMPLES]
    long temperaturePtr, humidityPtr, statusPtr
    
    OBJ
      f       : "FloatMath"
    
    PUB StartDHTnn(devicePin,DeviceModel,TempPtr,HumPtr,StatPtr) : result
    
      APin := devicePin
      Device := DeviceModel
    
      measurementCog := -1
      
    {{
        This method lauches the Measuring code in a new cog
        to read the DHTnn autonomously with variables updated
        every few seconds
    }}
    
      MeasurementInit(APin, @measuring, @MeasurementValues)
    
      temperaturePtr := TempPtr
      humidityPtr := HumPtr
      statusPtr := StatPtr
    
    PUB Stop
    {{
       stop cog if in use
    }}
    
        if measurementCog => 0
          cogstop(measurementCog)
    
    Pub DHTnn_Read | Data[5], Temp, Humid, ByteCount,BitCount,Pulsewidth,Parity,ptr,tr,hr
    {{
        This method reads the DHTnn device autonomously with variables located at
        the pointers updated every few seconds
    }}
                          'Apin is data line in from DHTnn
                          'Data[5] bytes received in order from DHTnn
                          'DATA = upper 8 bits of RH data
                          '     + lower 8 bits of RH data
                          '     + upper 8 bits of temperature data
                          '     + lower 8 bits of temperature data
                          '     + 8 bits check-sum (equals other 4 bytes added)
    
                          'ByteCount   - Index counter for data Bytes
                          'BitCount    - Index counter for bits within data bytes
                          'Pulsewidth  - Width of bits received from DHTnn, 26uS = 0, 70S=1, in clock ticks
                          'parity      - Boolean - parity for data from DHTnn
                          'clkpermicro - number of clock ticks per microsecond
                          'clkminpulse - the number of clock ticks for a pulsewidth value to be considered a 1
    
      clkpermicro := clkfreq / 1_000_000
      clkminpulse := clkpermicro * 48 ' Minimum 48 us 'high' pulse
    
      waitcnt(clkfreq*2+cnt)                ' Pause to allow DHTnn to stabilize
    
      DIRA[Apin]~~                          ' Set selected Pin to output
      OUTA[Apin]~~                          ' Pull Up selected Pin to start sequence
    
      Repeat ByteCount from 0 to 4
        Data[ByteCount]:=0                  ' Clear Data of Each Byte Before Input
      
      waitcnt(clkfreq/4+cnt)                ' Pause to allow DHTnn to stabilize
    
      ' Send a low to the DHTnn to request data
    
      DIRA[Apin]~~                          ' Set selected Pin to output
      OUTA[Apin]~                           ' Pull Down selected Pin for 500 uS to Request Data
    
      if device == 11
        waitcnt((clkpermicro * 20_000) + cnt) ' hold 20ms
      else
        waitcnt(clkfreq / 2000 + cnt)       ' Pause for 500uS
    
      OUTA[Apin]~~                          ' Return Pin to High
      DIRA[Apin]~                           ' Set Pin to Input and Release Control to DHTnn
      
      ' DHTnn reponds with a ready signal (80uS low, 80uS high, 40 uS low, before data)
    
      waitpne(|<Apin,|<Apin,0)              ' Wait for low, high, low sequence
      
      waitpeq(|<Apin,|<Apin,0)
      
      waitpne(|<Apin,|<Apin,0)
    
      MeasurementStart
      
      ' DHTnn will send 40 high bits where 0 is 26uS and 1 is 70uS
    
      repeat until measuring == 0
     
      ptr := 0
      
      Repeat ByteCount from 0 to 4          ' Store Data in 5 Bytes
        Repeat BitCount from 7 to 0         ' Receive Data by Bit, MSB to LSB
          pulsewidth := LONG[@MeasurementValues][ptr++]
          if pulsewidth > clkminpulse       ' If Pulse > min pulse then bit is 1 else 0 
            Data[ByteCount]|=|<BitCount     ' Store the bit in byte
      
      ' Check Parity
      parity := ((data[0]+data[1]+data[2]+data[3])& $ff)==(data[4]) 'Last byte equals sum of first four bytes
      
      ' Calculate Temperature
    
      if parity
        if (Device == 11)
          tr := data[2] & $7f               ' Pull from data2, mask MSB Bit
        else
          tr := data[2]                     ' Pull from data2
        
        tr <<= 8                            ' Put into upper byte
        tr += data[3]                       ' Add lower byte
    
        Temp := f.FFloat(tr)
    
        if (Device == 11)
          Temp := f.FDiv(Temp, 256.0)       ' Convert to DHT11 value
        else
          Temp := f.FMul(Temp, 0.1)         ' Convert to DHT22 value    
      
      ' Calculate Humidity
    
      if parity
        Humid:=data[0]                      ' Pull from data0
        Humid<<=8                           ' Put into upper byte
        Humid+=data[1]                      ' Add lower byte
    
        Humid := f.FFloat(Humid)
    
        if (Device == 11)
          Humid := f.FDiv(Humid, 256.0)     ' Convert to DHT11 value
        else
          Humid := f.FMul(Humid, 0.1)       ' Convert to DHT22 value    
    
      ' Return values to addresses provided in pointers
      
      if parity
        Long[temperaturePtr] := temp        ' Temperature
        Long[humidityPtr] := humid          ' Humidity
        Long[statusPtr] := 1                ' Parity ok
      else
        Long[statusPtr]:= 0                 ' Error
    
    ' Cog relies on these arguments, do not remove
    pub MeasurementInit(pAPin, pMeasuringStatus, pMeasurementValues) 
     
      measurementCog := cognew(@MeasureCog, @pAPin)
    
    pub MeasurementStart
      Long[statusPtr] := -1                  ' We're updating values    
    
      LONGFILL(@MeasurementValues, MAX_SAMPLES, 0)
    
      measuring := 1
    
    DAT
            ORG 0
    
    MeasureCog        
            mov             p1, par                         ' Get data pointer
            rdlong          APinNum, p1                     ' Get APin number
    
            add             p1, #4                          ' Get next pointer
            
            rdlong          measuringStatusPtr, p1          ' Get pointer to measuring value
    
            add             p1, #4                          ' Get next pointer
            rdlong          arrayPtrSave, p1                ' Get monitor array pointer
    
            mov             APinMask, #1                    ' Get pin mask
            shl             APinMask, APinNum 
    
            ' Used for timing pulses
    
            movi            ctra, #%11111                   ' Setup counter (always)
            mov             frqa, #1                        ' One count per tick
    
            ' Used for timeout in case of device failure
            
            movi            ctrb, #%11111                   ' Setup counter (always)
            mov             frqb, #1                        ' One count per tick
    
    wait
            rdlong          t1, measuringStatusPtr wz       ' Check "measuring" value
       if_z jmp             #wait                           ' Wait until "measuring" value nonzero
    
            ' Prepare for measurement
       
            mov             arrayPtr, arrayPtrSave          ' Set up array pointer
    
            mov             t2, #0                          ' Reset counter
            mov             phsb, #0                        ' Reset timeout
            
    measure
    
    ' Handle low-to-high (pulse gap)
    
            mov             t1, #0 wc                       ' Reset carry for waitpeq
    
            waitpeq         APinMask, APinMask              ' Wait for high state
    
            mov             t1, phsb                        ' Have we timed out?
            cmp             t1, timeoutTicks wz, wc         
      if_a  jmp             #done                           ' Yes, set done & start over
    
            mov             phsa, #0                        ' Reset counter
    
    ' Time high-to-low (pulse)
    
            waitpne         APinMask, APinMask              ' Wait for low state
            mov             t1, phsa                        ' Save counter value in t1, can't write directly to hub
            wrlong          t1, arrayPtr                    ' Save duration value
            add             arrayPtr, #4                    ' Set up for next array value
    
            mov             t1, phsb                        ' Have we timed out?
            cmp             t1, timeoutTicks wz, wc         
      if_a  jmp             #done                           ' Yes, set done & start over
    
            add             t2, #1                          ' Count values
            cmp             maxSample, t2 wz                ' Have we reached the limit?
      if_ne jmp             #measure                        ' No, back for more
    
    done    mov             t1, #0                          ' Yes, set status value to zero
            wrlong          t1, measuringStatusPtr          ' Update status value
    
            jmp             #wait                           ' We're done monitoring
            
    APinNum            long              0
    maxSample          long              MAX_SAMPLES
    measuringStatusPtr long              0
    arrayPtr           long              0 
    arrayPtrSave       long              0
    
    timeoutTicks       long              5 * 80_000_000 ' Assumes 80 MHz clock; 5 seconds
    
    APinMask      long              0
    
    p1            long              0
    
    t1            long              0
    t2            long              0
    
    {{
    
    ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │                                                   TERMS OF USE: MIT License                                                  │
    ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    │
    │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    │
    │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
    │is furnished to do so, subject to the following conditions:                                                                   │
    │                                                                                                                              │
    │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
    │                                                                                                                              │
    │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          │
    │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         │
    │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   │
    │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         │
    └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    }}
    
  • Ray:

    I don't see anything obviously wrong with the code. Does the Spin object work as you expect it to when you use it in a Spin project?
  • I got the program to run, it works as expected. The program provides the temp in C degrees, so I will have to figure out how to convert tp F degrees. The problem I see is with the humidity read out, not what it is supposed to be. I tried changing the variable from float to integer, but that did not help.

    Ray
    rem test_temp.bas
    ' October 13, 2018
    ' Test of the CM2302 module on the WX Activity Board
    
    dim cm2302 as class using "DHTnn_Object.spin"
    'dim f as class using "FloatMath.spin"
    'dim fp as class using "FloatString.spin"
    
    
    
    
    let mscycles = clkfreq / 1000
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    dim temp#,humid#,misc#
    dim humid1
    
    cm2302.StartDHTnn(8,22,@temp#,@humid#,@misc#)
    
    do
    	cm2302.DHTnn_Read()
    	print "Temp ";temp#;"  Humid  ";humid#
    	pausems 3000
    loop
    
    Propeller Version 1 on COM4
    Loading G:/fastspin/programs/test_temp/test_temp.binary to hub memory
    8676 bytes sent
    Verifying RAM ... OK
    [ Entering terminal mode. Type ESC or Control-C to exit. ]
    Temp 24.500 Humid 1.1034E+09
    Temp 24.600 Humid 1.1034E+09
    Temp 24.600 Humid 1.1034E+09
  • First a successful P2 and now this! I can hardly contain myself 👍😎

    What does the fastspin(BASIC) PASM code look like (assuming it does similar to PropBasic)?
    Failure is not an option...it's bundled with the software.
  • I attached the different files that fastspin(BASIC) provivided for my test_temp.bas program.

    Ray
  • @ersmith


    I tried to compiler the code snippet and got the following errors
    class fullduplex using "FullDuplexSerial.spin"
    class  Sd  using "fsrw.spin"           'dowloaded from OBEX
    dim ser as fullduplex
    dim sd  as fsrw
    
    
    ' test typewriter here
    dim chr  as ubyte
    ser.start(31, 30, 0, 115200)
    pausems(1000)
    do
       chr = ser.rx() 
        ser.tx(chr) 
       if  chr = 13 then 
            ser.tx(10)   
            ' handle  SDcard  commands here...but not ready yet
       end if
    loop
    
    Results of compiler, fastspin
    
    line 246              return @buf2 + (byteloc & constant(SECTORSIZE - 1))   
    line 483              floc := filesize & constant(!(SECTORSIZE - 1))  
    line 485              bufat := frem & constant(SECTORSIZE - 1)       
    
    
    
    
    fsrw.spin(246) error: Cannot handle expression yet
    fsrw.spin(483) error: Cannot handle expression yet
    fsrw.spin(485) error: Cannot handle expression yet
    
    
    
    
    
    
    

    Posted in the hope that it is helpful.

    Ron


  • @Rsadeika : To convert from C to F just multiply by 9/5 and add 32. You can do this in the print:
    	print "Temp "; (9.0/5.0)*temp# + 32.0;"  Humid  ";humid#
    
    Not sure why the humidity is coming out wrong; the code looks OK to me. You could trying to compile with optimization turned off (-O0) just in case there may be a fastspin optimizer bug.

    @Mickster : fastspin is an optimizing compiler, so the output is a little harder to read than PropBasic's. If you give it the -l switch it'll add the original code to the listing file as comments.

    @rsut : thanks for trying that! I think the problem is the constant(x) expression. I hope to fix that soon.

  • Thanks Eric

    It's a great piece of code on your part. I was trying port the sd code to pbasic but I could not fit the fast_spi_engine into one cog. (it's all inline pasm !!!)

    I decided not to try and re-invent the wheel and give your fastspin basic a try.

    Love it

    Ron
  • I am using spin2gui, and I chose, from the Options - No Optimizations, that seemed to have done the job. Before I was using, Default Optimizations, which produced the weird humidity# values. I also tried the Full Optimizations, it showed the first five lines of information, and it froze, never got to running the program. So, it might be something in your spin2gui Options, that might be causing a problem.

    The program below is outputting the correct values now, using-No Optimizations.

    Now that this is working, I would like to tackle the ADC component that is on the WX Activity Board. I know that there is PropGCC function for that, but that is in C. In the OBEX, the only thing that is available is for a different kind of ADC chip. Now if you have a C2fastspin(BASIC) conversion program, and the C source for the ADC , then I guess we could accomplish something.

    Now, in the mean time, I will have to try my hand at fsrw26, and see if I can make some progress. That looks like a fairly complicated Spin program.

    Ray
    rem test_temp.bas
    ' October 13, 2018
    ' Test of the CM2302 module on the WX Activity Board
    
    dim cm2302 as class using "DHTnn_Object.spin"
    
    
    let mscycles = clkfreq / 1000
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    dim temp#,humid#,misc#
    
    cm2302.StartDHTnn(8,22,@temp#,@humid#,@misc#)
    
    do
    	cm2302.DHTnn_Read()
    	print "Temp ";(9.0/5.0)*temp# + 32.0;"  Humid  ";humid#
    	pausems 3000
    
    loop
    
    Propeller Version 1 on COM4
    Loading G:/fastspin/programs/test_temp/test_temp.binary to hub memory
    12840 bytes sent
    Verifying RAM ... OK
    [ Entering terminal mode. Type ESC or Control-C to exit. ]
    Temp 73.040 Humid 55.500
    Temp 73.220 Humid 55.100
    Temp 73.220 Humid 55.100
    Temp 73.220 Humid 55.000
Sign In or Register to comment.