Need a sanity check: SX48 + 115200 baud + LCD + PS/2 keyboard
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
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
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.
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)
Do you have public example of UARTs using your scheduler technique? I'd like to try it in SX/B.
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)
Post Edited (JonnyMac) : 2/7/2007 2:17:46 AM GMT
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)