Shop OBEX P1 Docs P2 Docs Learn Events
Common mailbox/buffers for disconnecting the string handler from the driver code — Parallax Forums

Common mailbox/buffers for disconnecting the string handler from the driver code

I am close to releasing the new formatter which is based on jonnymacs jm_fullduplexserial object. I've totally decoupled the formatter from the pasm driver(s) so that I now can run multiple copies of the formatter to support up to 16 port/slots (actually an arbitrary value).

I now have a multiport serial driver (up to 16 ports although I did a version of 64 with 58 tested) and an LCD Driver. The same formatter code runs them both, and will do so for other drivers such as VGA, Keyboard, etc.

However, I discovered that configuring the ports with pin numbers, baud, etc was a problem. So my solution is to have a configuration mailbox to pass the configuration parameters and the standard port mailbox which contains the buffer head/tail/start/end pointers to the respective buffers.

Passing all those parameters was complex to say the least. So I abandoned that method (was working).

The alternative is to just edit a big list in the program with pin numbers for the relevant ports supported. They can still be changed on the fly, but this makes it easier to describe and implement from a users point of view.

Now the problem. Many of you know I have a real problem with not being able to force the location of code/variables/buffers into specifi hub locations. Well, this just bit me on the a....

Here is my big >100 line set of parameters that supports

  • Serial configuration (16 ports)
  • LCD configuration (1 port)
  • 16 port/slots of pointers to buffer head/tail/start/end
  • A buffer for each of the used port/slots (ie can be <16)

I have it contained in a DAT section. PropTool/pnut doesn't support include or ifdef :(
Here is this part of the code

'' ====================================================================================================================
dat { port/slots configuration, parameters and buffers}
'' ====================================================================================================================
'' WARNING: Within the following groups, the order and size must be maintained !!!

port_lcd_config     {3 longs}                   '\ LCD configuration
    long            @port_params                '| ptr to port_params
    byte            0<<7 | LCD_SLOT             '| inactive | slot#         where: 1=active, bbbb=slot#
    byte            LCD_CE                      '| LCD: Serial clock enable pin
    byte            LCD_RST                     '| LCD: Reset pin (can be reset by software)
    byte            LCD_DC                      '| LCD: Data / Command selection pin
    byte            LCD_SDA                     '| LCD: Serial Data MOSI pin
    byte            LCD_CLK                     '| LCD: Serial Clock pin
    byte            LCD_LED                     '| LCD: LED backlight enable pin (hi to enable - ~2.4mA)
    byte            LCD_SDO                     '/ LCD: Serial Data MISO pin

port_ser_config     {3 longs}                   '\ Multiport SERIAL configuration
    long            @port_params                '| ptr to port_params
port_control                                    '|  (keep together!)
    byte    {0}     0<<7 | 0<<6 | SER_RX  {63}  '| inactive | recv | pin#   where: {slot} 1=active, 1=xmit, bbbbbb=pin#
    byte    {1}     0<<7 | 1<<6 | SER_TX  {62}  '| inactive | xmit | pin#
    byte    {2}     0                           '| unused
    byte    {3}     0                           '| unused
    byte    {4}     0                           '| unused
    byte    {5}     0                           '| unused
    byte    {6}     0                           '| unused
    byte    {7}     0                           '| unused
    byte    {8}     0                           '| unused
    byte    {9}     0                           '| unused
    byte   {10}     0                           '| unused
    byte   {11}     0                           '| unused
    byte   {12}     0                           '| unused
    byte   {13}     0                           '| unused
    byte   {14}     0                           '| unused
    byte   {15}     0                           '/ unused

port_params     {16*4 = 64 longs}               '\ max (16 ports) of 4 longs... port[slot]: buffer ptrs to p_head, p_tail, p_start, p_end
    long    {0}     @BUF0                       '| \ {slot  0}  p_head    SERIAL-RX                 (ptr to current head of buffer)
    long            @BUF0                       '| |            p_tail       "                      (ptr to current tail of buffer)
    long            @BUF0                       '| |            p_start      "                      (ptr to start        of buffer)
    long            @BUF0+BUF_SIZE              '| /            p_end        "                      (ptr to end+1        of buffer)
    long    {1}     @BUF1                       '| \ {slot  1}  p_head    SERIAL-TX
    long            @BUF1                       '| |            p_tail       "
    long            @BUF1                       '| |            p_start      "
    long            @BUF1+BUF_SIZE              '| /            p_end        "
    long    {2}     @BUF2                       '| \ {slot  2}  p_head      LCD
    long            @BUF2                       '| |            p_tail       "
    long            @BUF2                       '| |            p_start      "
    long            @BUF2+BUF_SIZE              '| /            p_end        "
    long    {3}     0                           '| \ {slot  3}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long    {4}     0                           '| \ {slot  4}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long    {5}     0                           '| \ {slot  5}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long    {6}     0                           '| \ {slot  6}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long    {7}     0                           '| \ {slot  7}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long    {8}     0                           '| \ {slot  8}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long    {9}     0                           '| \ {slot  9}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long   {10}     0                           '| \ {slot 10}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long   {11}     0                           '| \ {slot 11}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long   {12}     0                           '| \ {slot 12}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long   {13}     0                           '| \ {slot 13}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long   {14}     0                           '| \ {slot 14}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '| /            p_end        "
    long   {15}     0                           '| \ {slot 15}  p_head    -unused-
    long            0                           '| |            p_tail       "
    long            0                           '| |            p_start      "
    long            0                           '/ /            p_end        "

' Define buffers for up to 16 port/slots...
'   -- 2 serial port/slots... (1 fdx uart serial ports)
'   -- 1 LCD port/slot
BUF0    byte            0[BUF_SIZE]              '\ serial buffer(s): tx must follow rx when using quick method "openfdxport"
BUF1    byte            0[BUF_SIZE]              '/
BUF2    byte            0[BUF_SIZE]              '> LCD buffer
    'add more if required (max 16)

'' ====================================================================================================================

Now the problem is this gets relocated. But the real issue is that the longs that contain addresses eg

  • @port_params
  • @BUF0
  • etc
    all insert an incorrect relative address into these hub locations. So when I pull these by reading via pasm or via long[port_control] I get the relative address, not the actual address where the buffers, etc are physically located.

As you can see, there are quite a number for a little piece of code that's about to grow substantially as more ports/drivers are added.

If the code is compiled without spin, then the physical hub addresses can be forced, and they work as expected.

Any ideas how to get past this without the cumbersome mess of physically re-plugging every corrected pointer back into the table?

Comments

  • Cluso99Cluso99 Posts: 18,069

    Here is a piece of spin code writing out to the same formatter object, but being redirected to either the serial port or the LCD. It works but the initialisation is terrible.

    Declare the objects

    OBJ
      ser    : "mpx_fullduplexserial"                               ' clusos multiport serial driver (based on jonnymacs serial) - suports fdx port
      lcd    : "mpx_fullduplexserial"                               ' clusos multiport serial driver (based on jonnymacs serial) - suports fdx port
      mpxdrv : "mpx_multiportserialdriver"                          ' multiport serial pasm driver in its' own cog 
      lcddrv : "lcd_textdriver_480x320"                             ' lcd text driver 4" ST7796
    

    Open the objects (note the parameters are now simplieied)

      sercog := mpxdrv.start(@port_control)                         ' start multiport serial pasm driver in new cog
      ser.openfdxport(@port_control, RX0_PORT_NUM, RX0, TX0, MODE, BAUD, @RXBUF0, RXBUF0_SIZE, 0, 0)
      lcd.openaltport(@port_params, TX2_PORT_NUM, TX_DIRN, @TXBUF2, @TXBUF2+TXBUF2_SIZE)
      lcdcog := lcddrv.start(@port_params + 4*4*TX2_PORT_NUM)    ' starts lcd pasm driver in new cog
    

    And to use the serial and lcd objects

      ser.fstr0(string("------------------------------------------------\r\n"))
      ser.fstr0(string("LCD driver v232 and handler v060 \r\n"))
      ser.fstr1(string("  Serial driver started in cog %1x\r\n"), sercog-1)
      ser.fstr1(string("  LCD    driver started in cog %1x\r\n"), lcdcog-1)
    
      lcd.fstr0(string("------------------------------------------------\r\n"))
      lcd.fstr0(string("LCD driver v232 and handler v060 \r\n"))
      lcd.fstr1(string("  Serial driver started in cog %1x\r\n"), sercog-1)
      lcd.fstr1(string("  LCD    driver started in cog %1x\r\n"), lcdcog-1)
    
  • Cluso99Cluso99 Posts: 18,069

    One potential suggestion was to compile the block as pasm only where the addresses would be correct, and then load the binary into the man code.

    While this would work for me, the real benefit of this method is for general use where we can have a single "format" object and many "driver" objects all working harmoniously together.

  • Cluso99Cluso99 Posts: 18,069

    These are the supported methods in the formatter object

    con { pst formatting }
    var
    pub null()
    con { start routines }
    PUB start_fdx_handler(p_params, rxslot, p_rxbufstart, bufsize) : status | p_rxparam_slot
    PUB start_rx_handler(p_params, xslot, p_bufstart, bufsize) : status | p_param_slot
    PUB start_tx_handler(p_params, xslot, p_bufstart, bufsize) : status | p_param_slot
    con { transmit routines }
    pub txChr(chr) : status | head, new
    pub txStr(p_str)
    pub txStrCR(p_str)
    pub txCR()
    pub txASCII(chr)
    pub txDump(addr1, addr2) | addr, addrend, i, j, mask                        
    pub txn(chr, n)
    pub txFlush()
    pub setStripLF(n)                                               ' 0=OFF, 1=ON
    con { receive routines }
    pub rxChr() : chr | tail, new
    pub rxStr(p_str) | addr, chr
    pub rxCheck() : chr
    PUB rxPeek() : status
    pub rxAvail() : count
    pub rxTime(ms) : chr | mstix, t
    pub rxTix(tix) : chr | t
    pub rxFlush()
    pub setEcho(n)                                                  ' 0=OFF, 1=ON
    con { transmit unformatted strings }
    pub str(p_str)
    pub substr(p_str, len) | chr
    pub padstr(p_str, width, pad)
    con { transmit formatted strings }
    pub fstr0(p_str)
    pub fstr1(p_str, arg1)
    pub fstr2(p_str, arg1, arg2)
    pub fstr3(p_str, arg1, arg2, arg3)
    pub fstr4(p_str, arg1, arg2, arg3, arg4)
    pub fstr5(p_str, arg1, arg2, arg3, arg4, arg5)
    pub fstr6(p_str, arg1, arg2, arg3, arg4, arg5, arg6)
    pub format(p_str, p_args) | idx, c, asc, field, digits
    pri lcase(c) : result
    pri get_nargs(p_str) : p_str1, val1, val2 | c, sign
    con { transmit decimal/hex/octal/quarternary/binary values }
    pub fmt_number(value, base, digits, width, pad)
    pub dec(value)
    pub fdec(value, digits)
    pub jdec(value, digits, width, pad)
    pub dpdec(value, dp)
    pub jdpdec(value, dp, width, pad)
    pub hex(value)
    pub fhex(value, digits)
    pub jhex(value, digits, width, pad)
    pub oct(value)
    pub foct(value, digits)
    pub joct(value, digits, width, pad)
    pub qrt(value)
    pub fqrt(value, digits)
    pub jqrt(value, digits, width, pad)
    pub bin(value)
    pub fbin(value, digits)
    pub jbin(value, digits, width, pad)
    pub nstr_fmt_number(value, radix, digits, width, pad) : p_str        ' *** changed 19 AUG 2020 ***
    pub nstr_dec(value, digits) : p_str | sign, len
    pub nstr_usdec(value, digits) : p_str | len
    pub nstr_dpdec(value, dp) : p_str | len, byte scratch[12]
    pub nstr_itoa(value, radix, digits) : p_str | sign, len, d
    pub nstr_revstr(p_str) : result | first, len, last
    pub nstr_padstr(p_str, width, padchar) : p_pad | len
    con { documentation }
    pub start(p_portctl, rxxport, rxpin, rxmode, rxbaud, p_rxstart, p_rxend, txxport, txpin, txmode, txbaud, p_txstart, p_txend)
    pub openport(p_portctl, xport, xpin, xdirn, xmode, xbaud, p_xstart, p_xend) : status | spmode, baudcfg
    pub closeport(p_portctl, xport, xpin)
    pub setStripLF(n)                                       ' 0=OFF, 1=ON   optionally strip <lf> when transmitting characters
    pub setEcho(n)                                          ' 0=OFF, 1=ON   optionally echo received characters to the transmitter
    pub txChr(chr) | n, p, head, new                        '* xmit a character
    pub txStr(p_str)                                        '* xmit a formatted string
    pub txStrCR(p_str)                                      '* xmit a formatted string followed by <cr><lf>
    pub txCR()                                              '* xmit <cr><lf>
    pub txASCII(chr)                                        '* xmit a character (converts $00-$1F & $7F-$FF to ".")
    pub txDump(addr1, addr2) | addr, addrend, i, j, mask    '* dumps hub memory as lines of 16 bytes + ASCII                    
    pub txn(chr, n)                                         '* xmit a character 'n' times
    pub txFlush() | p                                       '  wait until the xmit buffer and uart are empty 
    pub rxChr() : chr | p, head, tail, new                  '* recv a character
    pub rxStr(p_str) | addr, chr                            '* recv a 0 terminated string (<cr> terminates entry)
    pub rxCheck() : chr | p                                 '  checks rx buffer and returns -1 (True) if no chars available, else returns a char
    PUB rxPeek() : stat | p                                 '  checks rx buffer and returns -1 (True) if no chars available, else 0 (False)
    pub rxAvail() : count | p                               '  checks rx buffer and returns the number of characters in the buffer, 0 = none
    pub rxTime(ms) : chr | mstix, t                         '* waist up to ms for a character, returns -1 (True) if no chars available, else returns a char
    pub rxTix(tix) : chr | t                                '* waits up to clock-ticks for a char, returns -1 (True) if no chars available, else returns a char
    pub rxFlush()                                           '  flushes (clears) the rx buffer
    pub str(p_str)                                          '* xmit an un-formatted string
    pub substr(p_str, len) | chr                            '* xmit an un-formatted string with a maximum length
    pub padstr(p_str, width, pad)                           '* xmit an un-formatted string of 'width' characters padded using the 'pad' character
    pub fstr0(p_str)                                        '* xmit a formatted string
    pub fstr1(p_str, arg1)                                  '* xmit a formatted string with 1 variable
    pub fstr2(p_str, arg1, arg2)                            '* xmit a formatted string with 2 variables
    pub fstr3(p_str, arg1, arg2, arg3)                      '* xmit a formatted string with 3 variables
    pub fstr4(p_str, arg1, arg2, arg3, arg4)                '* xmit a formatted string with 4 variables
    pub fstr5(p_str, arg1, arg2, arg3, arg4, arg5)          '* xmit a formatted string with 5 variables
    pub fstr6(p_str, arg1, arg2, arg3, arg4, arg5, arg6)    '* xmit a formatted string with 6 variables
    pub format(p_str, p_args) | idx, c, asc, field, digits  '* xmit a formatted string with n variables
    pub fmt_number(value, base, digits, width, pad)         '  -- decimal/hex/octal/quarternary/binary
    pub dec(value)                                          '  -- decimal
    pub fdec(value, digits)                                 '  -- decimal and...
    pub jdec(value, digits, width, pad)                     '  -- decimal and...
    pub dpdec(value, dp)                                    '  -- decimal and...
    pub jdpdec(value, dp, width, pad)                       '  -- decimal and...
    pub hex(value)                                          '  -- hex
    pub fhex(value, digits)                                 '  -- hex and...
    pub jhex(value, digits, width, pad)                     '  -- hex and...
    pub oct(value)                                          '  -- octal
    pub foct(value, digits)                                 '  -- octal and...
    pub joct(value, digits, width, pad)                     '  -- octal and...
    pub qrt(value)                                          '  -- quarternary
    pub fqrt(value, digits)                                 '  -- quarternary and...
    pub jqrt(value, digits, width, pad)                     '  -- quarternary and...
    pub bin(value)                                          '  -- binary
    pub fbin(value, digits)                                 '  -- binary and...
    pub jbin(value, digits, width, pad)                     '  -- binary and...
    

    You will probably recognise most of them! They are from jonnymacs fantastic jm-fullduplexserial and jm_nstr objects. Thanks Jon :)

Sign In or Register to comment.