Shop OBEX P1 Docs P2 Docs Learn Events
Need a sanity check: SX48 + 115200 baud + LCD + PS/2 keyboard — Parallax Forums

Need a sanity check: SX48 + 115200 baud + LCD + PS/2 keyboard

danieldaniel Posts: 231
edited 2007-03-01 01:03 in General Discussion
I'm needing a bit of a sanity check. I have an industrial opportunity to build rather than buy.

The device will monitor sporadic bi-directional serial traffic at up to 115,200 baud, manage a small (e.g., 2x20) LCD, and take user input from both a PS/2 keyboard and a couple of pushbuttons. Upon pushbutton input, the device will need to insert a 16 to 64 byte string (of user entered data) into one of the serial lines.

I'd like to use SX/B.

It would be nice to use the SX48 protoboard with the 50 MHz oscillator and an added on-board serial buffer chip.

I lack sufficient experience this particular realm to go out on the limb by myself, and so I thought I would ask "Is it doable; what am I forgetting to consider?"

Daniel

Comments

  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-02-06 20:51
    Due to the PS/2 Keyboard requirement, I haven't seen any driver or hardware to support that on the SX. However, there is a new design recently posted on the Basic Stamp forum for PS/2 keyboards that I put together last night. It should not be hard to convert over to the SX/B as I am working on that over the next week or so.

    You may also want to consider the Propeller chip as it already has driver support for PS/2 keyboard, mouse, NTSC video and VGA.

    The remaining items (LCD, 115200 baud and pushbuttons) should be do-able on the SX-28.

    Good luck.
  • pjvpjv Posts: 1,903
    edited 2007-02-06 21:24
    Hi Daniel;

    Sure, I have done button input, PS/2 keyboard input, LCD output and 115200 serial bidirectional comms. Also, these can all be operated simultaneously in assembler ..... not in SX/B (I believe, as SX/B is not multi-tasking).

    So it's do-able but quite a bit of work to get it all right and rock-solid. To keep the timings and interactions simple, you will want to use an RTOS of some sort; a simple scheduler will do.

    I make products similar to this commercially, so I know its possible.

    I can guide you to a degree, but as I'm in this game on a commercial basis, you'll have to do the work yourself.

    Alternately, we can do a commercial arrangement with you.

    Cheers,

    Peter (pjv)
  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-02-06 23:32
    Peter,

    Do you have public example of UARTs using your scheduler technique? I'd like to try it in SX/B.
  • pjvpjv Posts: 1,903
    edited 2007-02-07 00:21
    Hi Jon;

    Sure, I'll dig out an appropriate one and post it.

    The main issue (I have) with SX/B is when it sits and waits for a time-out. Such as the pause function when receiving or sending serial data. Instead, if such pauses would simply return to the scheduler which then would dispatch the next task, you would then have a simple co-operative RTOS. That then wil permit numerous tasks to operate "simultaneously".

    I have done quite a bit more work on that front (eventhough there appeared to be minimal interest from the forum) to push this forward. Hopefully soon I can be ready to properly approach Terry (and others as appropriate) to investigate the changes required to SX/B for implementation of this concept. And hopefully we can get this implemented.

    I really think it not that onerous, and would have a tremendous benefit.

    More later.

    Cheers,

    Peter (pjv)
  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-02-07 02:01
    To be fair, SX/B is designed for guys more on my level than yours! I'm looking forward to seeing your stuff. SX/B is very flexible, and with the ability to create custom functions and subroutines perhaps an RTOS is possible -- might be a little fun to try. Our (EFX-TEK) customers are often asking for things we just can't do with the BS1 or BS2.

    Post Edited (JonnyMac) : 2/7/2007 2:17:46 AM GMT
  • pjvpjv Posts: 1,903
    edited 2007-03-01 01:03
    Hi All / JonnyMac;

    Earlier this month I promised to dig out a UART running under my simple scheduler. Well, finally I got time to do that and tweak it a bit so it can be quite simply modified.
    The formatting on the code display in this window gets all screwed up, so for easier reading, download the attached file.
    The sample uses state machines to send at string of data at 9600 baud.... a non- ASCII counter twice as well as carriage retrurn and line feed.
    Simultaneously it can (have not tested) also receive data at 9600.


    id 'Sched01' ; Feb 11, 2007
    ;for demonstration purposes to show a virtual serial UART at 9600 baud.
      Device SX28, OscHS3, Turbo, Optionx ;new assembler
    ;  Device watchdog   ;turn the watchdog on
    ;  Device bor42    ;turn brown-out detect on
    ;  Device carryx    ;turn extended carry on
    ;  Device protect    ;turn program read protection on
      Freq 50_000_000   ;default run speed = 50MHz
      Reset Initialize   ;start at label on reset
      IRC_Cal IRC_Slow   ;
    ;Constants for the Mode register settings
    ModeComp equ $08    ;mode for port B comparator swap access
    ModeBPend equ $09    ;mode for port B change detect sawp access 
    ModeBEdge equ $0A    ;mode for port B change rising edge selection (0)
    ModeBEnable equ $0B    ;mode for port B change detection enable (0)
    ModeSchmidt equ $0C    ;mode for port  BC bit Schmidt trigger enable (0)
    ModeLevel equ $0D    ;mode for port ABC bit CMOS level selection (0)
    ModePullup equ $0E    ;mode for port ABC bit pullup selection (0)
    ModeTristate equ $0F    ;mode for port ABC bit output direction selection (0)
    ;Constants for the option register
    ;      +---------------------------- 0 for Wreg at address 1
    ;      |+--------------------------- 0 for RTCC roll over interrupt enable
    ;      ||+-------------------------- 0 for RTCC increment on instruction clock
    ;      |||+------------------------- 0 for RTCC rising edge increment
    ;      |||| +----------------------- 0 for RTCC prescaler assignment
    ;      |||| |+---------------------- Prescaler 2
    ;      |||| ||+--------------------- Prescaler 1  
    ;      |||| |||+-------------------- Prescaler 0 14kHz watchdog; 000 is 16 mSec
    ;      |||| ||||
    RTCC_Dis_Ext_H2L__WDT = %1111_1000   ;
    RTCC_Dis_Int_H2L__WDT = %1101_1000   ;
    RTCC_Ena_Ext_H2L__WDT = %1011_1000   ;
    RTCC_Ena_Int_H2L__WDT = %1001_1000   ;
    Wreg_Dis_Ext_H2L__WDT = %0111_1000   ;
    Wreg_Dis_Int_H2L__WDT = %0101_1000   ;
    Wreg_Ena_Ext_H2L__WDT = %0011_1000   ;
    Wreg_Ena_Int_H2L__WDT = %0001_1000   ;
     
    IntConst equ -100    ;2 usec base tick at 50 MHz; for situations that require precise baud timing use -104 instead of -100
     
      org 8
    Flags  ds 1    ;
    IntFlag  equ Flags.0    ;indicates an interrupt has occurred
    ReceivedFlag equ Flags.1    ;indicates a byte has been received
      org $10
    Timer10uSec ds 1    ;down counts number of 2.5 uSec ticks toward one 10 uSec tick
    Timer100uSec ds 1    ;down counts number of 10 uSec ticks toward one 100 uSec tick
    Timer1mSec ds 1    ;downcounts number of 100 uSec ticks toward one 1 mSec tick
    Timer10mSec ds 1    ;downcounts number of 1 mSec ticks toward one 10 mSec tick
    Timer100mSec ds 1    ;downcounts number of 10 mSec ticks toward one 100 mSec tick
    Timer1Sec ds 1    ;downcounts number of 100 mSec ticks toward one 1 Second tick
    RXTimer  ds 1    ;tick counter for RXUART
    RXState  ds 1    ;current state holder for RXUART
    RXShifter ds 1    ;receive shift register
    ReceivedByte ds 1    ;holds received byte
    TXTimer  ds 1    ;tick counter for TXUART
    TXState  ds 1    ;current state holder for TXUART
    TXShifter ds 1    ;transmit shift register
    BitCounter ds 1    ;bit counter for transmitter
    StringState ds 1    ;current state holder for string sequence
    CharGen  ds 1    ;up counting character generator 0 through 255
     
      org 0    ;
    Interrupt setb IntFlag    ;indicate that an interrupt has occurred
      mov w,#IntConst   ;
      retiw     ;
     
     
    Initialize ;Program starts here on power-up and on reset; must be on page 0
    InitLevels mov m,#ModeLevel   ;Set to 0 for CMOS levels
      mov !ra,#%0000   ;
      mov !rb,#%0000_0000   ;
      mov !rc,#%0000_0000   ;
    InitPullup mov m,#ModePullup   ;Set to 0 for pullups
      mov !ra,#%0000   ;
      mov !rb,#%0000_0000   ;
      mov !rc,#%0000_0000   ;
    InitTris mov m,#ModeTristate   ;Set to 0 for output
      clr ra    ;
      mov !ra,#%1111_0001   ;x,x,x,x _ x,x,serout,serin
      clr rb    ;
      mov !rb,#%0000_0000   ;
      clr rc    ;  
      mov !rc,#%0000_0000   ;
    ClrMem  clr fsr    ;beginning of ram
    ClrOne  setb fsr.4    ;stay in upper half
      clr ind    ;clear location
      incsz fsr    ;next location
      jmp  ClrOne    ;continue clearing
      mov Timer10uSec,#5   ;initialize down counter to  5 * 2 uSec = 10 uSec
      mov Timer100uSec,#10  ;initialize down counter to 10 * 10 uSec = 100 uSec
      mov Timer1mSec,#10   ;initialize down counter to 10 * 100 uSec = 1 mSec
      mov Timer10mSec,#10   ;initialize down counter to 10 * 1 mSec = 10 mSec
      mov Timer100mSec,#10  ;initialize down counter to 10 * 10 mSec = 100 mSec
      mov Timer1Sec,#10   ;initialize down counter to 10 * 100 mSec = 1 Sec
    InitRTCC clr rtcc    ;
      mov !option,#wreg_Ena_Int_H2L__WDT ;
      clr Flags    ;
    InitUARTs mov RXTimer,#1   ;begin now
      mov RXState,#StartSearch  ;begin by looking for START bit
      mov TXTimer,#1   ;begin now
      mov TXState,#TXIdle   ;nothing to send yet
      mov StringState,#StringIdle  ;nothing to send yet
     
     
    ;MainLine Task Scheduler  =======================================================================================================
    Main  sb IntFlag    ;
      jmp Main    ;wait here until an interrupt has happened
      clrb IntFlag    ;acknowledge the interrupt
    
     
    Tick2uSec bank 0    ;point to timer RAM
      decsz Timer10uSec   ;one 2 uSec tick off 10 uSec timer
      jmp Main    ;timer has not expired
    
     
    Tick10uSec mov Timer10uSec,#5   ;reload 10 uSec down counter with 5 * 2 uSec = 10 uSec
        call Receiver   ;
        call Transmitter   ;if active, send next bit
      decsz Timer100uSec   ;one 10 uSec tick off 100 uSec timer
      jmp Main    ;timer has not expired
    
     
    Tick100uSec mov Timer100uSec,#10  ;reload 100 uSec down counter with 10 * 10 uSec = 100 uSec
      decsz Timer1mSec   ;one 100 uSec tick off 1 mSec timer
      jmp Main    ;timer has not expired
    
     
    Tick1mSec mov Timer1mSec,#10   ;reload 1 mSec down counter with 10 * 100 uSec = 1 mSec
        call TXString   ;send a character in the string
      decsz Timer10mSec   ;one 1 mSec tick off 10 mSec timer
      jmp Main    ;timer has not expired
    
     
    Tick10mSec mov Timer10mSec,#10   ;reload 10 mSec down counter with 10 * 1 mSec = 10 mSec
        mov StringState,#SendChar1  ;initiate a string transmission
      decsz Timer100mSec   ;one 10 mSec tick off 100 mSec timer
      jmp Main    ;timer has not expired
    
     
    Tick100mSec mov Timer100mSec,#10  ;reload 100 mSec down counter with 10 * 10 mSec = 100 mSec
      decsz Timer1Sec   ;one 100 mSec tick off 1 Sec timer
      jmp Main    ;timer has not expired
    
     
    Tick1Sec mov Timer1Sec,#10   ;reload 1 Sec down counter with 10 * 100 mSec = 1 Sec
      jmp Main    ;loop in this scheduler; regulated by the interrupt tick
    
    ;THE SECTION ABOVE IS ONE STANDARD SCHEDULER TEMPLATE (with the exception of the scheduled UART calls)
    ;Typically you can delete the timed sections that are slower than your needs.
     
     
    ;Receive UART =======================================================================================================================================
    ;The 9600 baud UART is oversampled at 5X, making one sart bit sample every 20 uSec
    RXLine = ra.0
     
    Receiver decsz RXTimer    ;test for passing of scheduled number of ticks
      retp     ;not yet...... return to scheduler
      mov pc,RXState   ;jump to active state
     
    StartSearch mov RXTimer,#2   ;reload START sample timer with 20 uSec (2 ticks of 10 uSec)
      snb RXLine    ;test for start level
      retp     ;no start found..... return to scheduler
    
     
    StartFound mov RXTimer,#12   ;sample first bit 120 uSec after detection of the START bit (12 ticks of 10 uSec)
      mov RXShifter,#%1000_0000  ;put a sentinel in the shifter
      mov RXState,#GetBits  ;at next tick start gathering bits
      retp     ;return to scheduler
     
    GetBits  snb RXLine    ;
      stc     ;a high was detected
      rr RXShifter   ;pull the bit in
      mov RXTimer,#10   ;sample next bit in 100 uSec (10 ticks of 10 uSec)
      sc     ;test for sentinel shifted out..... end of reception
      retp     ;not done... return to scheduler
    
     
    AllReceived mov RXState,#StartSearch  ;next time begin searching for a new START bit
      mov RXTimer,#12   ;skip over the time of a STOP bit
      mov ReceivedByte,RXShifter  ;save the received byte
      setb ReceivedFlag   ;indicate a byte has been received
      retp     ;8 bits received and interpreted... return to scheduler
     
     
    ;Transmit UART =========================================================================================================
    ;The 9600 baud transmitter tests every 10 uSec to see if a transmission has been posted by another routine
    TXLine = ra.1
     
    Transmitter decsz TXTimer    ;test for passing of scheduled number of ticks
      retp     ;not yet...... return to scheduler
      mov pc,TXState   ;jump to active state
        
    TXIdle  mov TXTimer,#1   ;reload timer with 10 uSec (1 tick of 10 uSec)
      retp     ;return to scheduler
     
    StartOut clrb TXLine    ;trigger a START bit
      mov BitCounter,#9   ;8 data bits plus 1 stop bit after the start
      mov TXState,#SendBits  ;next time send first bit
      mov TXTimer,#10   ;first bit 100 uSec from now (10 ticks of 10 uSec
      retp     ;return to scheduler
     
    SendBits snb TXShifter.0   ;test for bit level
      setb TxLine    ;send a high
      sb TXShifter.0   ;
      clrb TXLine    ;send a low
      mov TXTimer,#10   ;next bit 100 uSec from now (10 ticks of 10 uSec)
      rr TXShifter   ;ready next bit
      decsz BitCounter   ;test for byte plus stop bit done
      retp     ;not done..... return to scheduler
      setb TXLine    ;stop bit
      mov TXState,#TXIdle   ;
      mov TXTimer,#100   ;reload timer with 10 uSec (1 tick of 10 uSec)
      retp     ;return to scheduler
     
     
    ;TXString ============================================================================================================================
    ;Sends a character every 100 usec if transmitting UART is available
    
     
    TXString cse TXState,#TXIdle   ;test for transmitter UART to be free
      retp     ;still busy
      mov pc,StringState   ;jump to prep the next character in the string
     
    StringIdle retp     ;no character to transmit
     
    SendChar1 mov TXState,#StartOut  ;trigger transmitter
      mov TXShifter,CharGen  ;load a (non-ascii) counter value for transmission
      mov StringState,#SendChar2  ;next char in string
      retp     ;return to scheduler
     
    SendChar2 mov TXState,#StartOut  ;trigger transmitter
      mov TXShifter,CharGen  ;load a (non-ascii) counter value for transmission
      inc CharGen    ;modify data to be transmitted
      mov StringState,#SendChar3  ;next char in string
      retp     ;return to scheduler
     
    SendChar3 mov TXState,#StartOut  ;trigger transmitter
      mov TXShifter,#' '   ;load ascii 'space' for transmission
      mov StringState,#SendChar4  ;next char in string
      retp     ;return to scheduler
     
    SendChar4 mov TXState,#StartOut  ;trigger the transmitter to run
      mov TXShifter,#$0D   ;load a carriage return
      mov StringState,#SendChar5  ;next char in string
      retp     ;return to scheduler
     
    SendChar5 mov TXState,#StartOut  ;trigger the transmitter to run
      mov TXShifter,#$0A   ;load a line feed
      mov StringState,#StringIdle  ;done with string
      retp     ;return to scheduler
     
    ;=============================================================================================================================
     
     
    

    This is not the only (or best) way to tackle the UART, just one chosen to show how it interacts with the scheduler.

    Cheers,

    Peter (pjv)
Sign In or Register to comment.