+Vorticon Posted February 25 Share Posted February 25 49 minutes ago, TheBF said: Order of operations: - select the base CARD CRU address first -RESET bit 5 for clear to send -then add the displacement to get access to the UART - test UART bit 21 - if character is ready then: - read a byte from the UART - IMPORTANT! reset bit 18 on the uart after each character is received to reset the rcv buffer in the UART (bit 18 is the Receive interrupt enable bit, but needs to be touched even when not using interrrupt driven receive) - endif - re-select the CARD CRU address - set bit 5 to block further inputs Not shown is the fact that R12 is already set up with the base RS232 CRU address of >1300. I am mostly following that outline, except that I did not know that CTS was active LOW. Here's what it looks like now and it still does not work... sbz 5 ;activate cts line. ready to receive a @uartdis,r12 ;add uart displacement to cru base chkdsr tb 26 ;test rts pin. signal is inverted! jne chkdsr ;if line high then not ready chkbuf tb 21 ;test receive buffer jne chkbuf stcr r6,8 ;get byte into r6 sbz 18 ;reset buffer cru bit 21 mov @cruadr,r12 ;restore base rs232 card cru address sbo 5 ;inactivate cts line. not ready to receive swpb r6 The following works on the other hand although without any flow control: a @uartdis,r12 ;add uart displacement to cru base chkdsr tb 26 ;test rts pin. signal is inverted! jne chkdsr ;if line high then not ready chkbuf tb 21 ;test receive buffer jne chkbuf stcr r6,8 ;get byte into r6 sbz 18 ;reset buffer cru bit 21 swpb r6 Still stumped... Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted February 25 Share Posted February 25 52 minutes ago, Stuart said: Also worth pointing out that SBO, SBZ and TB can take negative values. So you can leave R12 pointing at the UART and use negative values to control the CTS line. The offset is (from memory) *twice* the difference in CRU bit numbers. So if R12 = >1340, you need a SBO -25 to switch on the card LED at address >130E. Good to remember, although it does make the code a little less clear. 1 Quote Link to comment Share on other sites More sharing options...
Stuart Posted February 25 Share Posted February 25 2 hours ago, Vorticon said: I'm trying to implement a simple low level data transfer routine for the RS232 card using RTS/CTS flow control and I'm not able to receive anything. The problem appears to be with the CTS control. According to Nouspikel, CRU bit 5 of the >1300 CRU base of the first RS232 card controls the CTS1 line. In the following excerpt, I first activate CTS, get the byte, then inactivate CTS and return to the calling routine (not shown). Removing the CTS parts allows me to receive data but I can't obviously control the flow. Anyone here familiar with the RS232 serial ops at the low level? sbo 5 ;activate cts line. ready to receive a @uartdis,r12 ;add uart displacement to cru base chkdsr tb 26 ;test rts pin. signal is inverted! jne chkdsr ;if line high then not ready chkbuf tb 21 ;test receive buffer jne chkbuf mov @cruadr,r12 ;restore base rs232 card cru address sbz 5 ;inactivate cts line. not ready to receive a @uartdis,r12 ;add uart displacement to cru base stcr r6,8 ;get byte into r6 swpb r6 sbz 18 ;reset buffer cru bit 21 Back to your original problem ... your TB 26 to test the RTS pin. That is actually testing the state or the 9902's RTS *output*. Are you trying to test the RTS pin from the other device? Don't think that is supported - you need to rely on the other device's DTR, which you typically monitor on the 9902's DSR input. If you remove the TB 26 line and jump after it, does it work? Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted February 25 Share Posted February 25 24 minutes ago, Stuart said: Back to your original problem ... your TB 26 to test the RTS pin. That is actually testing the state or the 9902's RTS *output*. Are you trying to test the RTS pin from the other device? Don't think that is supported - you need to rely on the other device's DTR, which you typically monitor on the 9902's DSR input. If you remove the TB 26 line and jump after it, does it work? YES! I replaced RTS with DSR (CRU 27) which is what Nouspikel does and it worked! I was indeed trying to test the RTS pin from the remote device... This is the kind of institutional knowledge that makes all the hair pulling worthwhile 😄 Thanks! So question: since I am controlling flow here, does it really matter what the baud setting is? EDIT: I'll answer my own question, and it's no. I tried it with 300 baud and 2400 baud, and it's looking like the actual transfer rate is between 110 and 300 baud. The reason it's that slow is that all the processing of the received byte is being done at high level in pcode, so for each byte a call is made to the receive routine in assembly, the byte is received and returned to the calling program, processed, and so on and so forth. This is further complicated by the fact that the pcode card needs to be turned off with each access to the RS232 card, which adds delays as well. This is the full routine for the curious. .ref pcodeon,pcodoff,rs232on,rs232of,uartdis,procret,cruadr mov r11,@procret bl @pcodoff bl @rs232on sbz 5 ;activate cts line. ready to receive a @uartdis,r12 ;add uart displacement to cru base chkdsr tb 27 ;test dsr pin. signal is inverted! jne chkdsr ;if line high then not ready chkbuf tb 21 ;test receive buffer jne chkbuf stcr r6,8 ;get byte into r6 sbz 18 ;reset buffer cru bit 21 swpb r6 mov @cruadr,r12 ;restore base rs232 card cru address sbo 5 ;inactivate cts line. not ready to receive mov r6,*r10 ;place byte on return stack bl @rs232of bl @pcodeon mov @procret,r11 b *r11 3 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 25 Share Posted February 25 (edited) You aren't doing anything a "normal" RS232 card needs to be turned on to do. CRU access works anyway with most cards. So you can leave p-code on. The enable bit handles memory access only, except for with some odd cards. Also don't forget that baud rate is about the bits in a character. You can send one character every second at 9600 baud. Edited February 25 by apersson850 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted February 25 Share Posted February 25 1 hour ago, apersson850 said: You aren't doing anything a "normal" RS232 card needs to be turned on to do. CRU access works anyway with most cards. So you can leave p-code on. The enable bit handles memory access only, except for with some odd cards. Keeping the pcode card on and not turning the RS232 card does not work. Maybe the reception buffer needs an active RS232 card for access? Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 25 Share Posted February 25 3 hours ago, Vorticon said: YES! I replaced RTS with DSR (CRU 27) which is what Nouspikel does and it worked! I was indeed trying to test the RTS pin from the remote device... This is the kind of institutional knowledge that makes all the hair pulling worthwhile 😄 Thanks! So question: since I am controlling flow here, does it really matter what the baud setting is? EDIT: I'll answer my own question, and it's no. I tried it with 300 baud and 2400 baud, and it's looking like the actual transfer rate is between 110 and 300 baud. The reason it's that slow is that all the processing of the received byte is being done at high level in pcode, so for each byte a call is made to the receive routine in assembly, the byte is received and returned to the calling program, processed, and so on and so forth. This is further complicated by the fact that the pcode card needs to be turned off with each access to the RS232 card, which adds delays as well. This is the full routine for the curious. .ref pcodeon,pcodoff,rs232on,rs232of,uartdis,procret,cruadr mov r11,@procret bl @pcodoff bl @rs232on sbz 5 ;activate cts line. ready to receive a @uartdis,r12 ;add uart displacement to cru base chkdsr tb 27 ;test dsr pin. signal is inverted! jne chkdsr ;if line high then not ready chkbuf tb 21 ;test receive buffer jne chkbuf stcr r6,8 ;get byte into r6 sbz 18 ;reset buffer cru bit 21 swpb r6 mov @cruadr,r12 ;restore base rs232 card cru address sbo 5 ;inactivate cts line. not ready to receive mov r6,*r10 ;place byte on return stack bl @rs232of bl @pcodeon mov @procret,r11 b *r11 Very happy you are making progress. From what I understand in your code you are using the DSR handshake line before receiving. As far as I understand it you connected you app to PC or some other device DTR/DSR is typically used to establish that the devices are connected. This sentence from this web site is my understanding https://www.commfront.com/pages/3-easy-steps-to-understand-and-control-your-rs232-devices " DTR/DSR are normally ON or OFF for the whole connection session (e.g. Off-hook), while RTS/CTS are ON or OFF for each data transmission." So the CTS/RTS handshake is used to prevent data overruns. If you are using RS232/1 (primary UART) the CTS line manipulation as I showed will prevent a PC with hardware handshaking enabled, from over-running the TI-99. Your code is telling the sender that they are "clear to send" all the time. Oops missed the SBZ 5 LINE in your code. Since you have a slow polling program you will probably need to toggle the CTS to block the sender until you have put a character into its final home and your loop gets back to read the next character. If you are using RS232/2 I could not see a separate CTS line for that UART exposed on the TI-99 card. Maybe somebody else knows a secret I could not find. Once you have this working the better way to go will be enable RS232 on an interrupt and put the data into a queue. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted February 26 Share Posted February 26 25 minutes ago, TheBF said: Very happy you are making progress. From what I understand in your code you are using the DSR handshake line before receiving. As far as I understand it you connected you app to PC or some other device DTR/DSR is typically used to establish that the devices are connected. This sentence from this web site is my understanding https://www.commfront.com/pages/3-easy-steps-to-understand-and-control-your-rs232-devices " DTR/DSR are normally ON or OFF for the whole connection session (e.g. Off-hook), while RTS/CTS are ON or OFF for each data transmission." So the CTS/RTS handshake is used to prevent data overruns. If you are using RS232/1 (primary UART) the CTS line manipulation as I showed will prevent a PC with hardware handshaking enabled, from over-running the TI-99. Your code is telling the sender that they are "clear to send" all the time. Since you have a slow polling program you will probably need to toggle the CTS to block the sender until you have put a character into its final home and your loop gets back to read the next character. If you are using RS232/2 I could not see a separate CTS line for that UART exposed on the TI-99 card. Maybe somebody else knows a secret I could not find. Once you have this working the better way to go will be enable RS232 on an interrupt and put the data into a queue. I do toggle the CTS line in my code: activate on entry, deactivate on exit, which is how I'm preventing the TI from being overrun as you said. Otherwise I get a ton of dropped characters. Unfortunately the pcode system does not allow interrupts as far as I know. As things stand, I am now able to reliably transfer text source code from my PC to the TI under the pcode system and save it to disk. With a little bit manipulation, I should be able to do the same with raw binary files as well. That's the next step. But what I am eventually aiming at is a proper bidirectional file transfer protocol, albeit a simple one, namely XMODEM. I've studied the specs and I should be able to do it. Famous last words... 😁 This has been quite the rabbit hole! 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 26 Share Posted February 26 16 minutes ago, Vorticon said: I do toggle the CTS line in my code: activate on entry, deactivate on exit, which is how I'm preventing the TI from being overrun as you said. Otherwise I get a ton of dropped characters. Unfortunately the pcode system does not allow interrupts as far as I know. As things stand, I am now able to reliably transfer text source code from my PC to the TI under the pcode system and save it to disk. With a little bit manipulation, I should be able to do the same with raw binary files as well. That's the next step. But what I am eventually aiming at is a proper bidirectional file transfer protocol, albeit a simple one, namely XMODEM. I've studied the specs and I should be able to do it. Famous last words... 😁 This has been quite the rabbit hole! Yes I just noticed that line in your code and struck out my comment. Super. This is real progress. Congrats. Shame about the interrupts. That is the real secret to fast serial communication. Funny thing, I have been looking at the Xmodem protocol to put on my RS232 Forth to transfer files as well. I think I even found a version in a dialect of Forth but have not ported it. So much code so little time... 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 26 Share Posted February 26 9 hours ago, Vorticon said: Keeping the pcode card on and not turning the RS232 card does not work. Maybe the reception buffer needs an active RS232 card for access? With an original TI RS232 card I tried talking to the TMS 9902 without turning on the card, and it responded. Now I didn't do a full scale communication program, but still a bit weird you can't make that work. I don't remember exactly what I read, but I think it was some kind of status word. It did change if I first sent a reset to the TMS 9902 and read it, then read it again a little later without the reset. So I was definitely getting some data from the UART. Seems pretty weird if they would gate it differently depending on a TMS 9902 status. Anyway, I've never done any special serial communication with the p-system, as there has never been any reason to. Nothing to communicate with. So I have no knowledge from experience here. I've done out-of-the-ordinary parallel port communication under the p-system, but that's different. And then you do have to enable the card and disable the p-code card, since the parallel data buffers are in the memory map. Quote Unfortunately the pcode system does not allow interrupts as far as I know. But it does. Even with things that weren't available when it was designed. I know that for a fact, since I made my own real time clock. When I did, I linked the RTC's interrupt pin to the system interrupt request in the box. I tried writing a DSR which will display the current time in the upper right corner of the p-system's screen, and then let the RTC interrupt every 1/10 s to do that. It works. It can most certainly allow the RS232 card to interrupt too, but how well it works after that, I don't know. Timingwise, I mean. I haven't checked exactly what the system does with the incoming data either, if interrupt driven. One could hope you can just read them from the REMIN:, but I don't know exactly how that works. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted February 26 Share Posted February 26 4 hours ago, apersson850 said: With an original TI RS232 card I tried talking to the TMS 9902 without turning on the card, and it responded. Now I didn't do a full scale communication program, but still a bit weird you can't make that work. I don't remember exactly what I read, but I think it was some kind of status word. It did change if I first sent a reset to the TMS 9902 and read it, then read it again a little later without the reset. So I was definitely getting some data from the UART. Seems pretty weird if they would gate it differently depending on a TMS 9902 status. Anyway, I've never done any special serial communication with the p-system, as there has never been any reason to. Nothing to communicate with. So I have no knowledge from experience here. I've done out-of-the-ordinary parallel port communication under the p-system, but that's different. And then you do have to enable the card and disable the p-code card, since the parallel data buffers are in the memory map. But it does. Even with things that weren't available when it was designed. I know that for a fact, since I made my own real time clock. When I did, I linked the RTC's interrupt pin to the system interrupt request in the box. I tried writing a DSR which will display the current time in the upper right corner of the p-system's screen, and then let the RTC interrupt every 1/10 s to do that. It works. It can most certainly allow the RS232 card to interrupt too, but how well it works after that, I don't know. Timingwise, I mean. I haven't checked exactly what the system does with the incoming data either, if interrupt driven. One could hope you can just read them from the REMIN:, but I don't know exactly how that works. I am able to access the individual CRU bits without the card being turned on (I had tested that before with the card LED), but in the setting of actual serial communication it does not seem to work. As for interrupts, I thought I had read in the manual that interrupts were not supported. Apparently I read wrong. In any case, I've never worked with interrupts before, and while I do understand the concept, there is little in the EA manual to guide the uninitiated and it's not a topic that is usually taken up by the assembly language books. There is no question about its usefulness however, so I'd love to learn. Maybe @matthew180 would like to come up with one of his wonderful tutorials on the subject? 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 26 Share Posted February 26 I noticed before that you tested with the LED. But the LED is implemented with the same 74LS259 as is used to enable the card, so there's no way they can prevent that from responding with the card off. The first eight bits are always open. There is a technical possibility to not enable the TMS 9902 chips unless the card has been enabled first. With that I mean CRU access to these UART's could also be gated via card enable. But it is could, nothing more. It doesn't have to be like that. I did like you did with the LED (which didn't really prove anything more than the obvious), but I tested with the two TMS 9902 instead. I read out some status I think it was (via CRU) and got a certain value. Then I sent a reset command (via CRU) and read status again (via CRU). It had now changed. I read status once again (via CRU) and it was back to the first value. All this without turning on the card itself. Thus I'd say it was obvious that I could read a value that was different before and right after reset. From that condition I drew the conclusion that I was actually talking to the TMS 9902, not just reading some random electric signal from space. But again, I've not tried doing anything serious with this method. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 26 Share Posted February 26 (edited) 1 hour ago, Vorticon said: As for interrupts, I thought I had read in the manual that interrupts were not supported. Apparently I read wrong. In any case, I've never worked with interrupts before, and while I do understand the concept, there is little in the EA manual to guide the uninitiated and it's not a topic that is usually taken up by the assembly language books. There is no question about its usefulness however, so I'd love to learn. FYI, here is the TI RS232 DSR ROM disassembled and commented by Thierry Nouspikel and register numbers converted to R values by yours truly. Note the ISR at >A4092 – >A415C: RS232.a99 Also, see Thierry’s RS232 ISR discussion. ...lee Edited February 26 by Lee Stewart addendum 2 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted February 26 Share Posted February 26 34 minutes ago, Lee Stewart said: FYI, here is the TI RS232 DSR ROM disassembled and commented by Thierry Nouspikel and register numbers converted to R values by yours truly. Note the ISR at >A4092 – >A415C: RS232.a99 49.95 kB · 2 downloads Also, see Thierry’s RS232 ISR discussion. ...lee Thanks! Nice reference to have. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 26 Share Posted February 26 If you ever want to go down the interrupt controlled serial receive road, here is code I got from @InsaneMultitasker. I adapted it to my system and there are some improvements that can be made to manage the circular queue with less instructions, which speeds up the time spent in the interrupt code. That could be done in a version 2. This is pretty daunting if you have never worked with interrupts before and I don't think the TI-99 designers ever imagined this way of doing things. This is pretty clever magic IMHO. RS232-ISR.A99 2 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted February 26 Share Posted February 26 Yeah, baby steps, Sparks, baby steps... If you can tell which movie this came from you win the Internet 😄 1 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted February 26 Share Posted February 26 1 hour ago, TheBF said: If you ever want to go down the interrupt controlled serial receive road, here is code I got from @InsaneMultitasker. I adapted it to my system and there are some improvements that can be made to manage the circular queue with less instructions, which speeds up the time spent in the interrupt code. That could be done in a version 2. This is pretty daunting if you have never worked with interrupts before and I don't think the TI-99 designers ever imagined this way of doing things. This is pretty clever magic IMHO. RS232-ISR.A99 10.65 kB · 3 downloads Wow, 2016. Time sure files. One thing worth mentioning - that has been discussed in various topics- is if this code is used with a nano PEB serial port, the "card" must be enabled and disabled at appropriate times. Not relevant here but sometimes people adapt code to other devices. It is usually ok to leave the nanopeb rs232 CRU 'enabled' except when performing file IO via DSRLNK. IIRC, your improvements have to do with managing the circular buffer BEND/BSTART pointers within a memory range that allows for the use of ANDI to "reset" the buffer position without a comparison. Neat stuff Edit: @TheBF if you poke at a rev 2 some day, PM me and I'll dig up the last changes I made in TIMXT for comparison. 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 26 Share Posted February 26 58 minutes ago, InsaneMultitasker said: @TheBF if you poke at a rev 2 some day, PM me and I'll dig up the last changes I made in TIMXT for comparison. Thanks. I re-wrote the whole thing in Forth Assembler so it looks quite different but I will reciprocate and you can see what I did. The one thing that stopped me using it all the time was I got bad reactions when I tried to read the floppy drives. My system keeps interrupts running except during VDP access so maybe that's the problem. ?? Never figured it out. 2 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted February 26 Share Posted February 26 4 minutes ago, TheBF said: The one thing that stopped me using it all the time was I got bad reactions when I tried to read the floppy drives. My system keeps interrupts running except during VDP access so maybe that's the problem. ?? It -sounds- like R15 wasn't saved/restored within the DSR routine. * Implementation Notes: * Some peripheral cards, including TI and Myarc controllers rely * upon GPLWS R15 for VDP access. The DSRLNK routine has been * modified to save/restore R15 and disable/enable interrupts (LIMI 0/2) * directly before calling the DSR ROM routine. It may be necessary * to turn off the RS232 interrupt (or use handshaking) if a DSR * tries to do a LIMI 2 while servicing. (should not happen!) Here is the TIMXT DSRLNK. R15SAV is used to preserve GPLWS R15 (which is 'corrupted' by the rs232 init routine) and then it is restored in a few places. Interrupts are disabled though I think that's just standard fare, which means somewhere, ints must be enabled after the DSR call. I'm guessing the terminal emulator's main loop does this automatically. geb_dsr.txt 1 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 26 Share Posted February 26 This might explain it since I re-wrote DSRLiNK using more code I found by you on Atariage. I don't save R15 so I will give that a try. I disable interrupts in my wrapper that calls DSRLINK but the DSR ROM code itself if probably screwing that up. I will have to see what the real issue is. I might be able to just use CTS during the ISR and gate the sender from getting in my way. Thanks for all your assistance. 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 26 Share Posted February 26 (edited) Although the p-system will execute the interrupt service routine on the RS232 card, I've not investigated if it really has the proper pointers at >8300 for that queue system to work. The addresses from >8300 and a bit down are occupied by the PME inner interpreter when the p-system is running. Regarding the CRU enable for the TMS 9902 - I did notice that the PAL equations are published, so that can be found out. I just need to see what they imply. Edited February 26 by apersson850 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 27 Share Posted February 27 6 hours ago, TheBF said: This might explain it since I re-wrote DSRLiNK using more code I found by you on Atariage. I don't save R15 so I will give that a try. I disable interrupts in my wrapper that calls DSRLINK but the DSR ROM code itself if probably screwing that up. I will have to see what the real issue is. I might be able to just use CTS during the ISR and gate the sender from getting in my way. Thanks for all your assistance. FYI: Saving R15 did not fix the problem but I think it changed how things crash which is progress. There is something else I am missing. I will try pushing R12 before calling DSRLINK and popping R12 when it's done. I can't understand how that could be the problem though because I in different workspaces with DSRLINK. ?? Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted February 27 Share Posted February 27 2 hours ago, TheBF said: I will try pushing R12 before calling DSRLINK and popping R12 when it's done. I can't understand how that could be the problem though because I in different workspaces with DSRLINK. ?? Standard DSRLNK flips to GPLWS before the call. Whether that matters or not, I am not sure. It is forth, so maybe you need to pop before you push? 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted February 27 Share Posted February 27 3 hours ago, InsaneMultitasker said: Standard DSRLNK flips to GPLWS before the call. Whether that matters or not, I am not sure. It is forth, so maybe you need to pop before you push? It matters. There are paths in the DSR that won't work correctly if the workspace isn't GPLWS. That's why Classic99 warns about it. 3 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 27 Share Posted February 27 Yes, I noticed for example in the RS232 DSR for the interrupt service that they do a STWP R4, then address the queue pointer and other with the address @-offset(R4). Thus they hit the first words/bytes in scratch PAD RAM with @-224(R4) or @>FF20(R4). If the workspace isn't GPLWS at that time, then poofff... Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.