\ serial.fth \ a serial terminal for an XO-1, XO-1.5 or XO-1.75 \ by James Cameron \ usage: \ ok fl u:\serial.fth \ ok serial \ connect cable last \ cable to cable crossover pin map \ gnd to gnd (orange to orange) \ tx to rx (green to red) \ rx to tx (red to green) \ 3.3v not connected (black) \ to turn off the screen output of the target \ (removes the target scroll delay from the output) \ ok screen-ih remove-output \ -- \ identify laptop model : q ( -- 2|3|4 ) ofw-model$ drop d# 14 + c@ h# 30 - ; : xo-1? ( -- flag ) q 2 = ; : xo-1.5? ( -- flag ) q 3 = ; : xo-1.75? ( -- flag ) q 4 = ; \ queue implementation copied from dev/16550pkg/16550.fth d# 32768 constant /q struct /n field >head /n field >tail /q field >qdata constant /qstruct /qstruct buffer: read-q : init-q ( q -- ) 0 over >head ! 0 swap >tail ! ; : inc-q-ptr ( pointer-addr -- ) dup @ ca1+ dup /q = if drop 0 then swap ! ; : enque ( new-entry q -- ) >r r@ >tail @ r@ >head @ 2dup > if - /q then 1- ( entry tail head ) <> if r@ >qdata r@ >tail @ ca+ c! r@ >tail inc-q-ptr else drop then r> drop ; : deque? ( q -- false | entry true ) >r r@ >head @ r@ >tail @ <> if r@ >qdata r@ >head @ ca+ c@ r@ >head inc-q-ptr true else false then r> drop ; \ end of queue implementation \ serial interrupt handler for received data : si ( -- ) ukey read-q enque ; \ interrupt enable register UART_IER, table 1993, page 1547 : ier@ ( -- b ) h# 1 uart@ ; : ier! ( b -- ) h# 1 uart! ; \ receiver data available interrupt enable : ravie-on ( -- ) ier@ h# 1 or ier! ; : ravie-off ( -- ) ier@ h# 1 invert and ier! ; \ line control register UART_LCR, table 1998, page 1554 : ulcr@ ( -- b ) h# 3 uart@ ; : ulcr! ( b -- ) h# 3 uart! ; \ set break : sb-on ( -- ) ulcr@ h# 40 or ulcr! ; : sb-off ( -- ) ulcr@ h# 40 invert and ulcr! ; \ modem control register UART_MCR, table 1999, page 1555 : mcr@ ( -- b ) h# 4 uart@ ; : mcr! ( b -- ) h# 4 uart! ; \ OUT2 signal control, enable UART interrupts : out2-on ( -- ) mcr@ h# 8 or mcr! ; : out2-off ( -- ) mcr@ h# 8 invert and mcr! ; d# 1 value break-ms : send-break begin uemit? until sb-on break-ms ms sb-off ; : irq# ( irq# -- ) xo-1? xo-1.5? or if d# 4 exit then xo-1.75? if d# 24 exit then true abort" unrecognised model" ; \ enable serial interrupt : esi ['] si irq# interrupt-handler! irq# enable-interrupt ravie-on out2-on ; \ disable serial interrupt : dsi out2-off ravie-off irq# disable-interrupt ; \ on XO-1.5, enable-serial disables the camera and adds the serial \ instance handles to the multiplexor. on other models it is absent. [ifndef] enable-serial \ present on XO-1.5 : enable-serial ; [then] \ stop using the serial port as console \ (necessary to avoid noise from interconnected hosts) : serial-off fallback-out-ih remove-output fallback-in-ih remove-input ; \ resume using the serial port as console : serial-on fallback-out-ih add-output fallback-in-ih add-input ; defer key-state defer key-state-default : reset-key-state ['] key-state-default >data token@ to key-state ; : key-state-exit ( key -- ) uemit ; : key-state-exit? ( -- exit? ) ['] key-state >data token@ ['] key-state-exit = ; : key-state-c-a ( key -- ) \ list of recognised c-a sequences case 1 ( c-a ) of 1 uemit reset-key-state endof 2 ( c-b ) of send-break reset-key-state endof [char] b of send-break reset-key-state endof 4 ( c-d ) of ['] key-state-exit to key-state endof [char] k of ['] key-state-exit to key-state endof [char] K of ['] key-state-exit to key-state endof ( default ) reset-key-state endcase ; : key-state-run ( key -- ) dup 1 = if ['] key-state-c-a to key-state drop exit then \ c-a uemit ; ' key-state-run to key-state-default : outgoing key? if key key-state then ; : incoming begin read-q deque? while emit repeat ; : serial-help-0 green-letters ." serial terminal running," cr ." use c-a k to exit," cr ." use c-a c-b to send break," cr ." use c-a c-a to send a c-a." cr cancel cr ; : serial-help-1 cr green-letters ." serial terminal stopped." cancel cr ; : serial enable-serial serial-off read-q init-q esi reset-key-state serial-help-0 begin outgoing incoming key-state-exit? until dsi serial-help-1 ; \ FIXME: slow character performance, \ dump whole strings from read-q not characters \ FIXME: black background, by patching termemu, \ test matrix \ host XO-1.5, target XO-1.75, break fail; no effect, can keep up, \ host XO-1.5, target XO-1, break pass, can't keep up, \ host XO-1.75, target XO-1.5, break pass, can't keep up, \ host XO-1.75, target XO-1, break pass, can't keep up, \ host XO-1, target XO-1.75, break fail, can keep up, \ host XO-1, target XO-1.5, break pass, can't keep up, \ host XO-1.75, target XO-1.75, break fail, ubreak? does become set!