; > TestSrc.ExtIO TTL RISC OS 2+ POST external commands ; ; External interface for RISC OS ROM. ; provides entry points to send byte- and word- and string-sized objects ; and to receive byte- and word-sized objects ; ; A minimal set of opcodes should be used (ideally, only B, LDR and ADDS) ; so that a processor test may be validly included in the internal test ; sequence. ; ;------------------------------------------------------------------------ ; History ; ; Date Name Comment ; ---- ---- ------- ; 06-Dec-89 ArtG Initial version - split from `Begin` ; Release 0.2 for integration ; 31-Mar-90 ArtG Added ts_MoreText, cursor position, hex. ; 19-Apr-90 ArtG Added bus exercise commands ; 09-May-90 ArtG Changed LCD strobe to 12 pulses ; 15-May-90 ArtG Added ReadyByte : improves synchronization ; when ExtCmd execution toggles A21/A22. ; 18-Jun-90 ArtG Added CPR15 read/write functions ; 04-Oct-96 JRH Updated comments to refer to test box on A23. ; Added support for speaking to the test box when ; running from the 2nd ROM bank, conditioned on ; CanLiveOnROMCard. Needed because 2nd ROM bank ; isn't ghosted on the A23 line like the 1st bank. ; 04-May-99 KJB Modified to cope with >8M ROMs. ;------------------------------------------------------------------------ SUBT Test adapter interface ; ; The test adapter senses an access to the ROM with address line A23 high. ; ; 8M addressing space ROMs only use address lines A2 to A22, ; so if A23 is asserted it will be ignored (the ROMS are aliased ; into 16M of space). With no test adapter, the aliased ROM location will ; be read and may be recognised. The test adapter may selectively disable ; ROMs when A23 is high, causing arbitrary data to be read. This data ; should be dependent on the previous ROM read operation, and will ; therefore be predictably not equal to the data read when the ROMs are ; aliased. ; ; On a system with >8M of ROM, A23 is now meaningful, and there is no ; aliasing of the ROM image. In this case, we read a fixed location at the ; end of the ROM that always contains zero - if it reads as non-zero, the ; test adapter is signalling. ; ; ; This section determines whether the test interface adapter exists, and ; what variety is fitted (dumb, display or external) ; 3 read operations are performed (a WS operation): if all of these ; find a ROM alias then no adapter is fitted. ; ; If an adapter responds, then a RD operation is performed - 4 strobes then ; clocking 8 bits into r4. These bits may be all zeros (a dumb adapter) ; or all ones (a display adapter) or some other value (an external ; adapter) ; ts_GetCommand ROUT LDR r0,%01 ADD pc,pc,r0 01 & 0 ; delay to make a gap before reading LDR r3,%02 ADD pc,pc,r0 02 & ts_recover_time 03 ADDS r3,r3,r3 ; 16-loop delay BCC %03 ROUT ; ; Load up the registers for the test interface communication. ; ; If the ROM is >8M, we will use the fixed zero word in the ROM trailer. ; If not, we use the old scheme (in case someone is using an old ROM joiner ; that doesn't write the correct trailer.) Because the ROM is >8M, the ; trailer will be at an address with A23 set, as desired. ; ; KJB - note I haven't kept the purity of the minimal instruction set - ; I feel that it is unlikely that there ever will be a processor test, ; and if there is, then this won't be the only place where the purity ; has been broken... ASSERT ts_Alias_bits = 8*1024*1024 MOV r0,#0 LDR r1,[r0, #ts_ROMSIZE] ; size of ROM in bank 0 CMP r1,#8*1024*1024 SUBHI r2,r1,#20 ; zero word is at end-20 BHI %42 ; Point r2 at a word which contains 0 in 0-8MB physical space. ; Note that this code doesn't cope with the case where it can't find a zero ; word anywhere in the whole ROM. I don't think that this is a problem. MOV r0, #0 ; expected below MOV r2, #0 ; start of physical space 01 LDR r1, [r2, #4]! TEQ r1, r0 ; is it zero? BNE %01 ADD r2, r2, #ts_Alias_bits ; point to zero word in ghost 42 MOV r1, #-1 ; expected below 04 ; do an RD operation (four strobes) to ensure interface cleared LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 ; write a byte (initially, &90) to indicate readiness LDR r4,%20 ADD pc,pc,r0 20 & ts_ReadyByte_00 ADDS r14,r0,pc B ts_SendByte ; delay to make a gap between WRS and RD operations LDR r3,%05 ADD pc,pc,r0 05 & ts_recover_time 06 ADDS r3,r3,r3 ; 16-loop delay BCC %06 LDR r5,%07 ; counter for first 5 bits ADD pc,pc,r0 07 & 1 :SHL: (32 - 5) LDR r6,%08 ; counter for last 3 bits ADD pc,pc,r0 08 & 1 :SHL: (32 - 3) ADDS r4,r0,r0 ; input accumulator initialisation ; put the test interface into input mode LDR r3,[r2] ; 3 bit lead-in ADDS r3,r3,r1 ; (adapter detects WS operation) BCC ts_User_startup ; abort if no adapter present LDR r3,[r2] ; two more strobes, then waitloop ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 ; started input operation : wait for interface to be ready 09 LDR r3,[r2] ; read start bit repeatedly ADDS r3,r3,r1 ; (adapter detects RD operation) BCC %09 ; loop until interface is ready ; read the first 5 bits into r5 and the second 3 bits into r4 10 LDR r3,[r2] ; read a bit of the byte ADDS r3,r3,r1 ; .. if the test adapter is present, carry bit set ADCS r4,r4,r4 ; .. shift left and add in carry ADDS r5,r5,r5 ; loop until 5 bits are read BCC %10 ADDS r5,r4,r4 ; copy bits 7..3 to r5, bits 5..1 ADDS r4,r0,r0 ; and read the last 3 bits to r4 11 LDR r3,[r2] ; read a bit of the byte ADDS r3,r3,r1 ADCS r4,r4,r4 ADDS r6,r6,r6 ; loop until last 3 bits are read BCC %11 ; ; Command byte read in (split between r4 and r5) ; Pass the option bits (r4) to the function identified by r5. ; ADDS r5,r5,r5 ; index * 2 -> index * 4 LDR r3,%12 ; pc-relative ptr to command_table ADD pc,pc,r0 12 & ts_command_table - %13 ADDS r3,pc,r3 ; absolute pointer to command table ADDS r3,r3,r5 13 LDR r3,[r3] ; get table entry 14 ADD pc,pc,r3 ; (offset from command_table) & 0 ; necessary padding : pc must point ; to command table when r3 is added. ; ; This is the table of offsets to all the built-in functions. ; The top 5 bits of the command are used to index, so there are ; 32 possible entries, mostly illegal. ; Decoding of the function modifier bits is performed by multiple ; entries in this table. ; ; pc must point here when ADDS pc,r3,pc is executed ASSERT ((ts_command_table - %14) = 8) ts_command_table DCD (ts_Dealer_startup - ts_command_table) ; display interface ts_Windex DCD (ts_write_memory - ts_command_table) ; external tests ts_Rindex DCD (ts_read_memory - ts_command_table) ts_Eindex DCD (ts_execute - ts_command_table) ts_Bindex DCD (ts_bus_exercise - ts_command_table) DCD (ts_GetCommand - ts_command_table) ; dummy entry aligns CPR instructions ; to allow 4-bit option field ts_CWindex DCD (ts_write_cpr15l - ts_command_table) DCD (ts_write_cpr15h - ts_command_table) ts_CRindex DCD (ts_read_cpr15l - ts_command_table) DCD (ts_read_cpr15h - ts_command_table) ; pad the table out to 31 entries ; (leave space for display vector) OldOpt SETA {OPT} OPT OptNoList doffset SETA . WHILE doffset < (ts_command_table + (31 * 4)) ; illegal entries DCD (ts_GetCommand - ts_command_table) doffset SETA doffset + 4 WEND OPT OldOpt DCD (ts_Forced_startup - ts_command_table) ; dumb interface ; ; The indexes into the above table are needed in ExtCmd ... ; ts_WriteCmdByte * ((ts_Windex - ts_command_table) :SHL: 1) ts_ReadCmdByte * ((ts_Rindex - ts_command_table) :SHL: 1) ts_ExecuteCmdByte * ((ts_Eindex - ts_command_table) :SHL: 1) ts_BusExCmdByte * ((ts_Bindex - ts_command_table) :SHL: 1) ts_CPWCmdByte * ((ts_CWindex - ts_command_table) :SHL: 1) ts_CPRCmdByte * ((ts_CRindex - ts_command_table) :SHL: 1) ; ; Primitives for reading data from the external interface ; ; - Get a byte from the interface (into r4) ; - Get a (4 byte) word from the interface (into r4) ; ; Required register setup is presumed done by a recent ts_GetCommand. ; r0, r1 and r2 have critical values ; r14 is the link address ; ts_GetWord ROUT LDR r6,%01 ; counter for 4 bytes per word ADD pc,pc,r0 ; (bit set 4 left shifts from Carry) 01 & 1 :SHL: (32 - 4) B ts_Getdata ts_GetByte ROUT LDR r6,%01 ; counter for single byte ADD pc,pc,r0 01 & 1 :SHL: (32 - 1) ts_Getdata ROUT ADDS r4,r0,r0 ; input accumulator initialisation LDR r3,[r2] ; 3 bit lead-in ADDS r3,r3,r1 ; (adapter detects RD operation) LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 ; started input operation : now loop until r6 shifts into Carry 02 LDR r5,%03 ; counter for 8 bits per byte ADD pc,pc,r0 03 & 2_00000001000000010000000100000001 04 LDR r3,[r2] ; read start bit repeatedly ADDS r3,r3,r1 BCC %04 ; loop until interface is ready 05 LDR r3,[r2] ; read a bit of the byte ADDS r3,r3,r1 ADCS r4,r4,r4 ; SHL r4, add carry bit. ADDS r5,r5,r5 ; loop until byte is read BCC %05 ADDS r6,r6,r6 ; loop until word is read BCC %04 ADD pc,r0,r14 ; back to the caller ; ; Primitives for sending data to the interface ; ; - Send a byte to the interface (from r4 lsb) ; - Send a (4 byte) word to the interface (from r4) ; ; Required register setup is presumed done by a recent ts_GetCommand. ; r0, r1 and r2 have critical values ; r14 is the link address ; ts_SendWord ROUT LDR r6,%01 ; counter for 4 bytes per word ADD pc,pc,r0 ; (bit set 4 left shifts from Carry) 01 & 1 :SHL: (32 - 4) B ts_Putdata ts_SendByte ROUT LDR r6,%01 ; counter for single byte ADD pc,pc,r0 01 & (3 :SHL: 7) 02 ADDS r4,r4,r4 ;shift byte into highest 8 bits ADDS r6,r6,r6 BCC %02 ;stop when byte shifted, ;leaving bit 31 set in r6 ts_Putdata ROUT ; Wait - gap between successive WS attempts or successive bytes 01 LDR r3,%02 ADD pc,pc,r0 02 & ts_recover_time 03 ADDS r3,r3,r3 ; 16-loop delay BCC %03 LDR r3,[r2] ; Test for adapter ready for data ADDS r3,r3,r1 ; (adapter detects WS operation) LDR r3,[r2] ADDS r3,r3,r1 BCC %10 ; skip out if adapter not present LDR r3,[r2] ADDS r3,r3,r1 BCC %01 ; loop back until adapter is ready ; Adapter ready - loop around all the bits in the byte LDR r5,%04 ; load bits-per-byte counter ADD pc,pc,r0 04 & (1 :SHL: (32-8)) 05 LDR r3,%06 ; delay before sending bit ADD pc,pc,r0 06 & ts_recover_time 07 ADDS r3,r3,r3 ; 16-loop delay BCC %07 ; Send a single bit : 1 pulse for 1, 2 pulses for 0 LDR r3,[r2] ADDS r4,r4,r4 ; shift current bit into Carry LDRCC r3,[r2] ; second pulse if bit is 0 ; repeat until 8 bits are sent ADDS r5,r5,r5 BCC %05 ; Repeat for all the bytes to be sent (1 or 4) ADDS r6,r6,r6 BCC %01 ; Go to TXRDY to ensure the host sees the transmit request LDR r3,%08 ; delay before sending pattern ADD pc,pc,r0 08 & ts_recover_time 09 ADDS r3,r3,r3 ; 16-loop delay BCC %09 LDR r3,[r2] ADDS r3,r3,r1 ; dummy - space between pulses LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ; All sent - r14 holds the caller's return address 10 ADD pc,r0,r14 ; ; Reporting primitive ; ; - Send the text (nul-terminated, at r4) to the display ; ; Interface registers need to be set up : this function is called from test ; code rather than external interface code. ; ; The display is assumed to be a standard 16 character LCD module using ; the Hitachi HD44780 display controller. ; The 16-digit module uses a single 44780. This is an abnormal use of the ; controller, and requires it to be set to two-line mode, with the first ; 8 displayed characters on the first 'line', and the second 8 on the ; second 'line'. Characters sent to the second line must be written at ; character position 40 +. In order to permit different modules to be ; fitted to later adapters, it is suggested that the first 7 characters ; be treated as a 'title' line, and the second 8 as a 'comment' line. ; A space should always be placed at the end of the title line to ; split the display fields, unless there is no 'comment' line. ; Do not display characters across the two areas as though they adjoined ; (even though they do :-) ). ; ; The controller is operated in its 4-bit mode, which allows the interface ; to drive 4 bits of alpha information and 4 bits of control information. ; The bits in a transmitted byte are assigned as : ; ; bit 0 - D4 } 4-bit mode data bus ; 1 - D5 } ; 2 - D6 } ; 3 - D7 } ; ; 4 - RS Register Select : 0 for control, 1 for data ; ; 5 - } Unassigned ; 6 - } ; ; 7 - CPEN Interface control : 0 for enable, ; 1 for disable ; ; For each message sent, the display is first initialised, using the ; following sequence (each byte is sent as 2 bytes, high nibble first, ; with RS clear in bit 4 of each byte) ; After each byte, an RD operation is performed : this is used by the ; interface hardware to strobe the data into the display. ; ; ; The message addressed by r4 is then sent (data mode : RS set in each byte) ; until a 0 byte is encountered. ; ; ; This is the command sequence sent to initialise the display ; ts_initialise = &30,&30,&30,&20 ; power-up initialisation = &20,&80 ; 4 bit mode, two line, Font 0 = &00,&C0 ; Display on, no cursor visible = &00,&60 ; Incrementing display position, no shift = &80,&00 ; Set DD RAM address 0 = &00,&20 ; Cursor home = &00,&10 ; Display clear ts_initialise_end ASSERT ((ts_initialise_end - ts_initialise) / 2) < 32 ; ; This is the command sequence sent when continuation text is sent ; ts_extend = &00,&C0 ; Display on, cursor invisible = &00,&60 ; Incrementing display position, no shift ts_extend_end ASSERT ((ts_extend_end - ts_extend) / 2) < 32 ; ; One of these commands are sent when offset text is required ; ts_offset_table = &80,&00 ; Set DD RAM address 0 ts_offset_table_1 = &80,&10 ; Set DD RAM address 1 = &80,&20 ; Set DD RAM address 2 = &80,&30 ; Set DD RAM address 3 = &80,&40 ; Set DD RAM address 4 = &80,&50 ; Set DD RAM address 5 = &80,&60 ; Set DD RAM address 6 = &80,&70 ; Set DD RAM address 7 = &C0,&00 ; Set DD RAM address 40 = &C0,&10 ; Set DD RAM address 41 = &C0,&20 ; Set DD RAM address 42 = &C0,&30 ; Set DD RAM address 43 = &C0,&40 ; Set DD RAM address 44 = &C0,&50 ; Set DD RAM address 45 = &C0,&60 ; Set DD RAM address 46 = &C0,&70 ; Set DD RAM address 47 ; This assertion is forced by the code : each sequence assumed 2 bytes. ASSERT ((ts_offset_table_1 - ts_offset_table) = 2) ALIGN ; ; Here starts the code ... ; ts_SendQuit ROUT ; put this code BEFORE %16 ADD pc,r0,r14 ; ; ; Entry point for initialising the display and sending r4 text. ; ts_SendText ROUT ; ; Point to the command sequence to setup and clear the display ; LDR r0,%10 ; set zero in r0 ADD pc,pc,r0 10 & 0 LDR r7,%11 ; pointer to init sequence ADDS r7,pc,r7 ADD pc,pc,r0 11 & (ts_initialise - .) LDR r6,%12 ; length of init sequence ADD pc,pc,r0 12 & (1 :SHL: (32 - (ts_initialise_end - ts_initialise))) B ts_SendLCDCmd ; ; Entry point for adding text to current cursor position ; ts_MoreText ROUT LDR r0,%10 ; set zero in r0 ADD pc,pc,r0 10 & 0 LDR r7,%11 ; pointer to command sequence ADDS r7,pc,r7 ADD pc,pc,r0 11 & (ts_extend - .) LDR r6,%12 ; length of command sequence ADD pc,pc,r0 12 & (1 :SHL: (32 - (ts_extend_end - ts_extend))) B ts_SendLCDCmd ts_PosText ROUT ; ; Entry point for adding text at a specific cursor position ; Used iteratively by SendText, etc if cursor position command found. ; Offset into display is given in r6. ; LDR r0,%10 ; set zero in r0 ADD pc,pc,r0 10 & 0 LDR r7,%11 ; pointer to command sequence ADDS r7,pc,r7 ADD pc,pc,r0 11 & (ts_offset_table - .) ; offset * 2 into table of ADDS r6,r6,r6 ; offset command sequences ADDS r7,r7,r6 LDR r6,%12 ; length of command sequence ADD pc,pc,r0 12 & (1 :SHL: (32 - 2)) ; ; Entry point for writing arbitrary command strings. ; Set r7 to point to command string, r6 length (as tables above), ; Set r4 to point to following Data string (null-terminated). ; ts_SendLCDCmd ; Point r2 at a word which contains 0 in 0-8MB physical space. ; If this word still reads as 0 when its ghost/alias is read from 8-16MB space ; (A23 set) then we don't have a test box, otherwise we do. ; Note that this code doesn't cope with the case where it can't find a zero ; word anywhere in the whole ROM. I don't think that this is a problem. MOV r0, #0 ; ts_send_command_byte expects r0=0 MOV r2, #0 ; start of physical space 01 LDR r1, [r2, #4]! TEQ r1, r0 ; is it zero? BNE %01 ADD r2, r2, #ts_Alias_bits ; point to zero word in ghost 04 ; Wait - gap between successive WS attempts or successive bytes ts_send_command_byte ROUT LDR r3,%14 ADD pc,pc,r0 14 & ts_recover_time 15 ADDS r3,r3,r3 ; 16-loop delay BCC %15 LDR r1,%16 ; reload test register ADD pc,pc,r0 16 & (-1) LDR r3,[r2] ; Test for adapter ready for data ADDS r3,r3,r1 ; (adapter detects WS operation) BCC ts_SendQuit ; skip output : adapter not present ; (backward jump helps ensure LDR r3,[r2] ; only reads zero when adapter absent LDR r3,[r2] ; since previous bus data is nonzero) ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 BCC ts_send_command_byte ; loop back until adapter is ready ; Adapter ready - loop around all the bits in the byte LDR r5,%21 ; load byte-shift counter ... ADD pc,pc,r0 ; ... and bits-per-byte counter 21 & (1 :SHL: 8) + 1 ; 24 shifts + 8 shifts LDRB r1,[r7] 22 ADDS r1,r1,r1 ; shift byte up into m.s.d. ADDS r5,r5,r5 BCC %22 ; Send a single bit : 1 pulse for 1, 2 pulses for 0 23 LDR r3,[r2] ADDS r1,r1,r1 ; shift current bit into Carry LDRCC r3,[r2] ; second pulse if bit is 0 ; and wait for the inter-bit time LDR r3,%24 ADD pc,pc,r0 24 & ts_recover_time 25 ADDS r3,r3,r3 ; 16-loop delay BCC %25 ; repeat until 8 bits are sent ADDS r5,r5,r5 BCC %23 ; do a RD operation to strobe the data out LDR r5,%26 ADD pc,pc,r0 26 & (1 :SHL: (32 - 12)) 27 LDR r3,[r2] ADDS r5,r5,r5 BCC %27 ; Repeat for all the bytes to be sent (ts_initialise_end - ts_initialise) LDR r3,%33 ADD pc,pc,r0 33 & 1 ADDS r7,r7,r3 ; bump the pointer ADDS r6,r6,r6 ; bump the counter (shift left) BCC ts_send_command_byte ; ; Then send all the display bytes (in 4-bit mode) until a nul-terminator ; is reached. ; ; ; Send a single character (as two separate 4-bit fields) ; First, look to see if it's one of : ; ; NUL - end of text string ; 0x80 - 0xfe - cursor positioning ; 0xff - introduce a hex digit ; ts_send_text_byte ROUT LDR r1,%40 ; reload test register ADD pc,pc,r0 40 & (-1) LDRB r7,[r4] ADDS r3,r7,r1 ; test for nul terminator BCC ts_SendEnd ; ; Byte isn't null. Check for >= 0x80. ; LDR r6,%42 ; test for cursor control ADD pc,pc,r0 42 & (-&80) ; &8x means column x. ADDS r6,r7,r6 BCC ts_printable_char ; < &80 : write a character ; ; Carry set : r6 now holds (value - 0x80). Check for numeric escape (&ff). ; LDR r3,%43 ADD pc,pc,r0 43 & (-&7f) ADDS r3,r6,r3 BCC %47 ; ; Carry set : fetch a nybble from the top of r8 and display that. ; ADDS r8,r8,r8 ADCS r6,r0,r0 ADDS r8,r8,r8 ADCS r6,r6,r6 ADDS r8,r8,r8 ADCS r6,r6,r6 ADDS r8,r8,r8 ADCS r6,r6,r6 LDRB r7,[pc,r6] B ts_printable_char 45 = "0123456789ABCDEF" ; ; Not &ff : r6 holds cursor positioning offset (< &80). Skip over ; the cursor control byte and iterate thro' PosText to move ; typing position. ; 47 LDR r3, %48 ADD pc,pc,r0 48 & 1 ADDS r4,r3,r4 B ts_PosText ; ; Character is normal text : write it to the LCD. ; The shift loop is used to generate the inter-byte delay normally ; provided by ts_recover_time. Always make sure this is long enough. ; ts_printable_char ADDS r6,r0,r7 ; take a copy of character LDR r5,%51 ; load byte-shift counter ... ADD pc,pc,r0 ; ... and bits-per-byte counter 51 ; as a bitmask of the shift pattern & (1:SHL:8)+(1:SHL:4)+1 ; 24 shifts + 4 shifts + 4 shifts 52 ADDS r6,r6,r6 ; shift byte up into m.s.d. ADDS r0,r0,r0 ; slow this loop down - ensure it's ADDS r0,r0,r0 ; always slower than ts_recover_time ADDS r5,r5,r5 BCC %52 LDR r3,[r2] ; Test for adapter ready for data ADDS r3,r3,r1 ; (adapter detects WS operation) LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 BCC ts_printable_char ; loop back until adapter is ready ; Adapter ready - loop around all the bits in the byte ts_send_tbit_upper ; wait for the inter-bit time LDR r3,%55 ADD pc,pc,r0 55 & ts_recover_time 56 ADDS r3,r3,r3 ; 16-loop delay BCC %56 ; Send a single bit : 1 pulse for 1, 2 pulses for 0 LDR r3,[r2] ADDS r6,r6,r6 ; shift current bit into Carry LDRCC r3,[r2] ; second pulse if bit is 0 ; repeat until upper 4 bits are sent ADDS r5,r5,r5 BCC ts_send_tbit_upper ; then send the interface control bits LDR r1,%57 ADD pc,pc,r0 57 & (8 :SHL: 28) ; assert RS control pin ts_send_cbit_upper ; wait for the inter-bit time LDR r3,%58 ADD pc,pc,r0 58 & ts_recover_time 59 ADDS r3,r3,r3 ; 16-loop delay BCC %59 ; Send a single bit : 1 pulse for 1, 2 pulses for 0 LDR r3,[r2] ADDS r1,r1,r1 ; shift current bit into Carry LDRCC r3,[r2] ; second pulse if bit is 0 ADDS r5,r5,r5 BCC ts_send_cbit_upper ; ; do a RD operation to strobe the data out ; LDR r3,%61 ADD pc,pc,r0 61 & ts_recover_time 62 ADDS r3,r3,r3 ; 16-loop delay BCC %62 LDR r5,%63 ADD pc,pc,r0 63 & (1 :SHL: (32 - 12)) 64 LDR r3,[r2] ADDS r5,r5,r5 BCC %64 ; prepare to send the lower 4 bits out LDR r5,%70 ; bitcount mask for 4 data bits ADD pc,pc,r0 ; and 4 interface control bits 70 & (((1 :SHL: 4) + 1) :SHL: 24) ts_send_text_lower LDR r3,%71 ADD pc,pc,r0 71 & ts_recover_time 72 ADDS r3,r3,r3 ; 16-loop delay BCC %72 LDR r1,%73 ADD pc,pc,r0 73 & (-1) LDR r3,[r2] ; Test for adapter ready for data ADDS r3,r3,r1 ; (adapter detects WS operation) LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 BCC ts_send_text_lower ; loop back until adapter is ready ts_send_tbit_lower ; wait for the inter-bit time LDR r3,%76 ADD pc,pc,r0 76 & ts_recover_time 77 ADDS r3,r3,r3 ; 16-loop delay BCC %77 ; Send a single bit : 1 pulse for 1, 2 pulses for 0 LDR r3,[r2] ADDS r6,r6,r6 ; shift current bit into Carry LDRCC r3,[r2] ; second pulse if bit is 0 ; repeat until lower 4 bits are sent ADDS r5,r5,r5 BCC ts_send_tbit_lower ; then send the interface control bits LDR r1,%78 ADD pc,pc,r0 78 & (8 :SHL: 28) ; assert RS control pin ts_send_cbit_lower ; wait for the inter-bit time LDR r3,%80 ADD pc,pc,r0 80 & ts_recover_time 81 ADDS r3,r3,r3 ; 16-loop delay BCC %81 ; Send a single bit : 1 pulse for 1, 2 pulses for 0 LDR r3,[r2] ADDS r1,r1,r1 ; shift current bit into Carry LDRCC r3,[r2] ; second pulse if bit is 0 ADDS r5,r5,r5 BCC ts_send_cbit_lower ; ; do a RD operation to strobe the data out ; ; wait for the inter-bit time LDR r3,%82 ADD pc,pc,r0 82 & ts_recover_time 83 ADDS r3,r3,r3 ; 16-loop delay BCC %83 LDR r5,%84 ADD pc,pc,r0 84 & 1 :SHL: (32 - 12) 85 LDR r3,[r2] ADDS r5,r5,r5 BCC %85 ; Repeat for all the bytes to be sent (until nul terminator is found) LDR r3,%86 ADD pc,pc,r0 86 & 1 ADDS r4,r3,r4 ; bump text pointer B ts_send_text_byte ; ; Wait for about 1 seconds worth of LCD operation delays to ; permit the operator to read the text. ; Use of the interface's monitor allows this delay to be increased ; or decreased externally. ; ts_SendEnd ROUT LDR r7, %01 ADD pc,pc,r0 01 & (ts_pause_time + 1) ; must be an odd number ; to ensure pairs of zeros ASSERT ((ts_pause_time :AND: 1) = 0) 02 LDR r3,%03 ADD pc,pc,r0 03 & ts_recover_time 04 ADDS r3,r3,r3 ; 16-loop delay BCC %04 LDR r1,%05 ; reload test register ADD pc,pc,r0 05 & (-1) LDR r3,[r2] ; Test for adapter ready for data ADDS r3,r3,r1 ; (adapter detects WS operation) BCC ts_SendQuit ; skip output : adapter not present LDR r3,[r2] ADDS r3,r3,r1 LDR r3,[r2] ADDS r3,r3,r1 BCC %02 ; loop back until adapter is ready ; Adapter ready - loop around all the bits in the byte ; Note that each byte is actually 4 bits to the LCD module, ; so a even number must be sent or the display will get out ; of sync until the next display reset sequence. LDR r5,%10 ; bits-per-byte counter ADD pc,pc,r0 10 & (1 :SHL: 24) LDR r3,%11 ADD pc,pc,r0 11 & ts_recover_time ; wait before sending data bits 12 ADDS r3,r3,r3 ; for byte timing. BCC %12 ; Send a single bit : always 2 pulses for 0 13 LDR r3,[r2] LDR r3,[r2] ; and wait for the inter-bit time LDR r3,%14 ADD pc,pc,r0 14 & ts_recover_time 15 ADDS r3,r3,r3 ; 16-loop delay BCC %15 ; repeat until 8 bits are sent ADDS r5,r5,r5 BCC %13 ; do a RD operation to strobe the data out LDR r5,%16 ADD pc,pc,r0 16 & 1 :SHL: (32 - 12) 17 LDR r3,[r2] ADDS r5,r5,r5 BCC %17 ; repeat until a sufficient number of nuls are done ADDS r7,r7,r1 ; count down loop counter BCS %02 ADD pc,r0,r14 ; back to caller END