+mytek Posted April 30, 2016 Author Share Posted April 30, 2016 (edited) OK I wasn't far off on the idea that the data was inverted. Problem was when I took out the data inversion the first time I had forgotten to reverse both the STOP and START bits which were also inverted. So I went in and made those changes, and then stuff started to work... well sort of. It seems that when I send a listing as in LIST "R:" from within BASIC (or LIST #R: from within ASSEMBLER/EDITOR) the first 8 characters are garbled, but everything afterwards is fine So I got this on a scope and fed it a continuous stream of alternating bits 10101010 which is a capital 'U' in ASCII (ASCII 85 = 'U') . This was the same as used in the diagram above. So on the scope each bit including START and STOP were registering as 3.3 ms in duration which appears to be correct for 300 baud. And it rendered the same on the scope as on the diagram. But also just like when I sent the listing, the first few characters received were garbled, and then all is perfect thereafter. Very strange indeed. Here is the BASIC test program I used... 10 OPEN $1,12,0,"R:" 20 PUT #1,85 30 GOTO 20 I'm once again confused So here are the code changes thus far... 0850 ; SERIALOUT - FIRST INVERT DATA 0860 ; 0870 SEROUT 0880 NOP ;*** REMOVED EOR #$FF 0885 NOP ;*** NO INVERSION OF DATA 0890 STA BUFFER 0900 ; 0910 ; DISABLE INTERRUPTS 0920 ; 0930 SEI 0940 LDA #0 0950 STA NMIEN 0960 STA DMACTL 0970 ; 0980 ; SEND STARTBIT 0990 ; 1000 LDA #0 ;*** REMOVED INVERSION 1010 STA PORTA 1020 JSR BITWAIT 1030 ; 1040 ; SEND CHARACTER DATA 1050 ; 1060 LDY #8 1070 STY COUNT 1080 ; 1090 SENDBYTE 1100 LDA BUFFER 1110 STA PORTA 1130 ROR BUFFER 1140 JSR BITWAIT 1150 DEC COUNT 1160 BNE SENDBYTE 1170 ; 1180 ; SEND STOPBIT 1190 ; 1200 LDA #1 ;*** REMOVED INVERSION 1210 STA PORTA 1220 JSR BITWAIT - Michael EDIT: the listing problem was worse in the ASSEMBLER/EDITOR environment as can be seen below... The first line got pretty much toasted, and probably also put out some sort of weird control code that indented the second line of the listing. But if I press break and then reissue the command to list to the R: device, I get an identical result as above. Go figure? 3 friggin days spent on this project thus far but at least I'm making headway and seeing stuff appear in the terminal that is getting close to being right . Edited April 30, 2016 by mytekcontrols Quote Link to comment Share on other sites More sharing options...
ricortes Posted May 1, 2016 Share Posted May 1, 2016 Couple of caveats: I haven't looked at the .PDF or found my original book so I don't know what they are doing with the subroutine BITWAIT. I recall writing something to do a transfer from 8-bit to ST or IBM via J/S port. There is no doubt in my mind that I added a 1/2 bit delay to get the data to transfer properly. This insured that the receiver was synced to the middle of the data sent. I can't remember how I did it, it could have been as simple as having my BITWAIT type subroutine adjusted and called 3 times for start bit and twice for actual data. Anyway, it worked fine after that up to 19k BAUD. Old age is hitting me with a vengeance but I think you want 1.5 BITWAIT for the start bit and 1 BITWAIT for everything after that. 1 Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 1, 2016 Author Share Posted May 1, 2016 Couple of caveats: I haven't looked at the .PDF or found my original book so I don't know what they are doing with the subroutine BITWAIT. I recall writing something to do a transfer from 8-bit to ST or IBM via J/S port. There is no doubt in my mind that I added a 1/2 bit delay to get the data to transfer properly. This insured that the receiver was synced to the middle of the data sent. I can't remember how I did it, it could have been as simple as having my BITWAIT type subroutine adjusted and called 3 times for start bit and twice for actual data. Anyway, it worked fine after that up to 19k BAUD. Old age is hitting me with a vengeance but I think you want 1.5 BITWAIT for the start bit and 1 BITWAIT for everything after that. Thanks. I'll let you know what I find out. Also wondering if something isn't right with the 'handler' aspect, possibly stomping on my one byte data buffer initially and then some how clearing up later. I'm so close at this point to having what I want. - Michael Quote Link to comment Share on other sites More sharing options...
ricortes Posted May 1, 2016 Share Posted May 1, 2016 I promise, I will download the book so I can get out of the dark. ☺ Could be a STATUS being issued by the Atari. If the first chr is a @ or A, B, C, it is looking for a printer or [P, Q, R, S] it's looking for serial device R1-R4. If that is the case, you would just need something in the handler to respond w/o doing anything on the j/s port. Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 2, 2016 Author Share Posted May 2, 2016 (edited) I promise, I will download the book so I can get out of the dark. ☺ Could be a STATUS being issued by the Atari. If the first chr is a @ or A, B, C, it is looking for a printer or [P, Q, R, S] it's looking for serial device R1-R4. If that is the case, you would just need something in the handler to respond w/o doing anything on the j/s port. No worries I figured it out The PACTL commands were incorrect. It was amazing it even worked at all, although obviously not right. Here is the complete (fixed) R: Handler assembly listing... 10 ;********************************* 20 ;* R-Handler * 30 ;* JOY PORTA-0 R: DEVICE * 40 ;* Adapted from Hackerbook * 50 ;* (Page 72) * 60 ;* * 70 ;* INITIALIZE - BY CALLING $0689 * 80 ;* * 90 ;********************************* 0100 ; 0110 COUNT = $0600 0120 BUFFER = $0601 0130 RSENTRY = $032C 0140 PACTL = $D302 0150 PORTA = $D300 0160 NMIEN = $D40E 0170 DMACTL = $D400 0180 EOL = $9B 0190 CR = $0D 0200 LF = $0A 0210 K = 150 110 & 300 BAUD 0220 L = 6 300 BAUD 0230 ; L=18 FOR 110 BAUD 0240 ; 0250 *=$0602 0260 ; 0270 HANDLTAB 0280 .WORD OPEN-1 0290 .WORD CLOSE-1 0300 .WORD GETBYTE-1 0310 .WORD PUTBYTE-1 0320 .WORD STATUS-1 0330 .WORD SPECIAL-1 0340 .BYTE 0,0,0,0 FILL REST WITH 0 0350 ; 0360 ; THE OPEN ROUTINE 0370 ; 0380 OPEN = * 0390 INIT 0400 LDA #$38 0410 STA PACTL 0420 LDA #1 SELECT TXD BIT 0430 STA PORTA 0440 LDA #$3C 0450 STA PACTL 0460 LDA #1 0470 STA PORTA 0480 SUCCESS 0490 LDY #1 0500 RTS 0510 ; 0520 ; THE CLOSE DUMMY ROUTINE 0530 ; ONLY RETURN SUCCESS IN Y (1) 0540 ; 0550 CLOSE = SUCCESS 0560 NOTIMPL 0570 LDY #146 RETURN WITH Y=146 0580 RTS 0590 ; 0600 ; THE FOLLOWING COMMANDS ARE 0610 ; NOT IMPLEMENTED SO GET ERROR 0620 ; CODE 146 0630 ; 0640 GETBYTE = NOTIMPL 0650 STATUS = NOTIMPL 0660 SPECIAL = NOTIMPL 0670 ; THE PUTBYTE COMMAND 0680 ; DATA IN ACCU 0690 ; STATUS IN Y (=1) 0700 ; 0710 PUTBYTE 0720 CMP #EOL 0730 BNE NOEOL 0740 ; 0750 ; IF EOL GIVE CRLF TO DEVICE 0760 ; 0770 LDA #CR 0780 JSR SEROUT 0790 LDA #LF 0800 NOEOL 0810 JSR SEROUT 0820 LDY #1 0830 RTS 0840 ; 0850 ; SERIALOUT 0860 ; 0870 SEROUT 0880 STA BUFFER PRESERVE ACC 0890 ; 0900 ; DISABLE INTERRUPTS 0910 ; 0920 SEI 0930 LDA #0 0940 STA NMIEN 0950 STA DMACTL 0960 ; 0970 ; SEND STARTBIT 0980 ; 0990 LDA #0 1000 STA PORTA 1010 JSR BITWAIT 1020 ; 1030 ; SEND CHARACTER DATA 1040 ; 1050 LDY #8 1060 STY COUNT 1070 ; 1080 SENDBYTE 1090 LDA BUFFER 1100 STA PORTA 1110 ROR BUFFER 1120 JSR BITWAIT 1130 DEC COUNT 1140 BNE SENDBYTE 1150 ; 1160 ; SEND 2 STOPBITS 1170 ; 1180 LDA #1 1190 STA PORTA 1200 JSR BITWAIT 1210 JSR BITWAIT 1220 ; 1230 ; ENABLE INTERRUPTS 1240 ; 1250 LDA #$22 1260 STA DMACTL 1270 LDA #$FF 1280 STA NMIEN 1290 CLI 1300 RTS DONE SENDING 1310 ; 1320 ; THE BIT TIMING ROUTINE 1330 ; FOR AN EXACT BAUDRATE 1340 ; 1350 BITWAIT 1360 LDX #K 1370 LOOPK 1380 LDY #L 1390 LOOPL 1400 DEY 1410 BNE LOOPL 1420 DEX 1430 BNE LOOPK 1440 RTS 1450 ; 1460 ; ROUTINE FOR INSTALLING THE 1470 ; RS232 HANDLER 1480 ; 1490 INITHAN 1500 LDA #'R DEVICE NAME 1510 STA RSENTRY 1520 LDA #HANDLTAB&255 1530 STA RSENTRY+1 1540 LDA #HANDLTAB/256 1550 STA RSENTRY+2 1560 JMP OPEN 1570 .END Download Atari Compatible Assembly Code: JOYRHAND.ASM To test under the ASSEMBLER/EDITOR CART do the following: ENTER #D:JOYRHAND.ASM<CR> ASM<CR> BUG<CR> G589<CR> X<CR> LIST #R:<CR> You can also hop into BASIC by going to DOS and then load a disk based version so you don't need to yank out the cartridge (BASIC++). Enter the following code to send a CR/LF following by all the printable ASCII characters. 10 OPEN #1,12,0,"R:" 20 PUT #1,13:PUT #1,10 30 FOR NUM=0 TO 94 40 PUT #1,32+NUM 50 NEXT NUM And of course LIST "R:" will send a BASIC listing via the joystick serial connection. Later I'll put together a BASIC program that will automatically load the handler code and initialize it. In order to actual use this as a 'real' RS232 connection you will need to add a simple circuit to level shift and invert the TTL signal coming from Pin 1 on joystick #1. The upper half of the circuit in the following diagram will do the trick. Also it might be necessary to jumper pin 7 to 8 as well (you can try it without, but my computer terminal didn't do anything without it). So basically this can be built inside the D-Sub 9F shell on the joystick side, with pin #1 as the TTL-TXD connection, pin #7 as +5V, and pin #8 as GND. The 10K resistor is optional since the Atari already has current limiting resistors inline with all of the joystick ports. If you can't find a BC557 transistor (I certainly couldn't), then substitute any general purpose PNP transistor such as the 2N2907. And yes both connectors (Terminal and Joystick) use the same 9 pin D-Sub female connector so be sure to mark which end is which. Enjoy - Michael EDIT: Oh yeah don't forget to set your RS232 Terminal to 1 start bit, 8 data bits, 2 stop bits, parity = none, no handshake, 300 baud. Any protocol should work (ANSI, ect.). Edited May 2, 2016 by mytekcontrols 4 Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 2, 2016 Author Share Posted May 2, 2016 Opps! That should have been: G689<CR> to initialize the handler from the DEBUGGER. - Michael Quote Link to comment Share on other sites More sharing options...
gozar Posted May 2, 2016 Share Posted May 2, 2016 Could the Atari joystick ports communicate with an Arduino Mini pro by directly connecting the RX/TX pins (https://www.arduino.cc/en/Main/arduinoBoardProMini)? Quote Link to comment Share on other sites More sharing options...
Kyle22 Posted May 2, 2016 Share Posted May 2, 2016 Could the Atari joystick ports communicate with an Arduino Mini pro by directly connecting the RX/TX pins (https://www.arduino.cc/en/Main/arduinoBoardProMini)? It should work as long as your Arduino is tolerant of 5V on the pins. 1 Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 2, 2016 Author Share Posted May 2, 2016 (edited) Could the Atari joystick ports communicate with an Arduino Mini pro by directly connecting the RX/TX pins (https://www.arduino.cc/en/Main/arduinoBoardProMini)? I agree with Kyle, there should be no problem. I do stuff like this with PIC's all the time, and the Arduino has similar I/O characteristics. The only thing I would suggest is maybe using a 3K pull-up to +5V, since the Atari's PIA being TTL has a rather feeble logic high state. But you'll only need to do this if you are experiencing erratic behavior. I take it your going to use the Aruino's built-in UART. Now I have a question of my own. Does anyone know of a good program to do a dump of Page 6 memory and create either BASIC data statements or maybe better yet a string variable equivalent for the data? - Michael Edited May 2, 2016 by mytekcontrols Quote Link to comment Share on other sites More sharing options...
evilmoo Posted May 2, 2016 Share Posted May 2, 2016 Now I have a question of my own. Does anyone know of a good program to do a dump of Page 6 memory and create either BASIC data statements or maybe better yet a string variable equivalent for the data? I was compelled to see how rusty my brain is: 10 for i=1536 to 1791 step 8 30 print i;" data ";peek(i); 30 for j=1 to 7 40 print ",";peek(i+j); 50 next j:print 60 next i 2 Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 2, 2016 Author Share Posted May 2, 2016 I was compelled to see how rusty my brain is: 10 for i=1536 to 1791 step 8 30 print i;" data ";peek(i); 30 for j=1 to 7 40 print ",";peek(i+j); 50 next j:print 60 next i I like that And it's very simple. Thank you, - Michael Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 3, 2016 Author Share Posted May 3, 2016 (edited) OK here's a simple BASIC loader and test routine. 10 REM ** LOAD R:HANDLER TO MEMORY ** 20 FOR AD=1538 TO 1691 30 READ B 40 POKE AD,B 50 NEXT AD 60 N=USR(1673):REM ** INIT R:HAND ** 70 REM 80 REM ======= PROGRAM MAIN ======= 100 REM setup input/output 110 REM 120 OPEN #1,4,0,"K:" 130 OPEN #2,12,0,"R:" 140 REM 150 REM clear screen & prompt input 160 REM 170 GRAPHICS 0:? "READY " 180 REM 190 REM get key and send to R: device 200 REM 210 GET #1,KEY:PUT #2,KEY:GOTO 210 220 REM 4000 DATA 17,6,37,6,40,6,43,6 4010 DATA 40,6,40,6,0,0,0,0 4020 DATA 169,56,141,2,211,169,1,141 4030 DATA 0,211,169,60,141,2,211,169 4040 DATA 1,141,0,211,160,1,96,160 4050 DATA 146,96,201,155,208,7,169,13 4060 DATA 32,61,6,169,10,32,61,6 4070 DATA 160,1,96,141,1,6,120,169 4080 DATA 0,141,14,212,141,0,212,169 4090 DATA 0,141,0,211,32,126,6,160 4100 DATA 8,140,0,6,173,1,6,141 4110 DATA 0,211,110,1,6,32,126,6 4120 DATA 206,0,6,208,239,169,1,141 4130 DATA 0,211,32,126,6,32,126,6 4140 DATA 169,34,141,0,212,169,255,141 4150 DATA 14,212,88,96,162,150,160,6 4160 DATA 136,208,253,202,208,248,96,104 4170 DATA 169,82,141,44,3,169,2,141 4180 DATA 45,3,169,6,141,46,3,76 4190 DATA 18,6 Download BASIC File: RHANDOUT.BAS This little program essentially does 3 things... Loads R: Handler code into Page 6 memory Initializes the new handler Redirects keyboard input to the R: device So what you have is a very simple RS232 terminal program running on your Atari. Now keep in mind that this is running the bare essentials, so it doesn't understand things like backspace or delete, which if pressed will send out some strange symbols. But it does recognize the RETURN key, and will send a <CR><LF>. The purpose of this little program is to give someone a basis to build up on and develop their own unique twist. Enjoy - Michael EDIT: Hey I think I'm getting my Atari programming legs back Edited May 3, 2016 by mytekcontrols 4 Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 4, 2016 Author Share Posted May 4, 2016 Question: Is there someway to read the 6520 PIA port to know what the output pin state is? The reason I am asking, is that I would like to write a variation of this code that respects the other pins on the port that I'm using to send out the serial data. So let's say this code gets combined with someone's BASIC program that also manipulates bits as outputs. I don't want this routine to stomp all over it and change any of the other output pin logic states. I know I can implement masking to prevent this, but that assumes I can read the logic state of the port pins to begin with which I haven't figured out how that can be done for outputs. - Michael Quote Link to comment Share on other sites More sharing options...
Rybags Posted May 4, 2016 Share Posted May 4, 2016 The PORT register is read/write. If in the data direction mode you can use AND/OR to existing value to set which pins you want as input or output. When it's in the default data mode, you can read it and use logic functions to perform output as needed and can do so without disturbing other pins. If a pin is configured for input then obviously it's state reflects if it's grounded or not. But writing back either value is no problem. Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 4, 2016 Author Share Posted May 4, 2016 (edited) The PORT register is read/write. If in the data direction mode you can use AND/OR to existing value to set which pins you want as input or output. When it's in the default data mode, you can read it and use logic functions to perform output as needed and can do so without disturbing other pins. If a pin is configured for input then obviously it's state reflects if it's grounded or not. But writing back either value is no problem. Hmmm... I think we might possibly be talking about two different things. So here is the scenario. Let's say all outputs have been set to output mode like in the code below. LDA #$38 STA PACTL LDA #$FF Set port bits to all outputs STA PORTA LDA #$3C STA PACTL And now we desire to have a ML program manipulating just one bit (or in other words, one output pin) of PORTA. This code won't work as desired because it obviously will set bit 1 to a logic high, but it will also set all other bits (0,2-7) to a logic low. LDA #%00000010 STA PORTA all bits changed However if I only want to set Bit 1 to high and leave all the other bits alone, I would normally want to do something like this. LDA #%00000010 ORA PORTA only bit 1 changes And this would work great if it were a normal memory location in RAM. But unless I am doing something wrong, this doesn't seem to work for a PIA port. When the PIA bits are set to outputs, they don't appear to be readable --- only writable. Now of course if my ML routine was in charge of everything, I could simply shadow the PIA Port in RAM and then use that as a mask to either OR (set specific bits) or AND (clear specific bits). But I don't have that luxury when a BASIC program may also be manipulating Port bits. So I guess what I am really asking, is there a way going through the Atari OS to have my ML routine only toggle a specific bit on a Port, without affecting others that a BASIC program is using for itself? - Michael Edited May 4, 2016 by mytekcontrols Quote Link to comment Share on other sites More sharing options...
Rybags Posted May 5, 2016 Share Posted May 5, 2016 (edited) You just described what I said. The register is read/write, as in it will contain the output setting previously set. So all you need to do if only using 1 or 2 bits is to read the existing value, then use logic instructions to do your own bitsettings without disturbing the others. But generally I doubt that any software using the ports would bother to try and coexist with other things in that way. When using the ports for custom I/O you generally have a purpose made interface cable and just plugging it in means you're obscuring all the other pins from possible use anyway. Though of course you have 2 ports sharing the one register but that's why you set the data direction first. For bits that are set to input, it doesn't matter what value you store to the data register anyway. Edited May 5, 2016 by Rybags Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 5, 2016 Author Share Posted May 5, 2016 You just described what I said. The register is read/write, as in it will contain the output setting previously set. So all you need to do if only using 1 or 2 bits is to read the existing value, then use logic instructions to do your own bitsettings without disturbing the others. Rybags I apologize. Previous to my question I had run some tests that suggested that reading the port wasn't yielding the same information as what had been set. Well I don't know what I changed, but I just re-ran that test and yes just like you said the register is read/write and the info matches. So sorry for my confusion, and thank you for having the patience to explain, and then re-explain. Best regards -- Michael 2 Quote Link to comment Share on other sites More sharing options...
ricortes Posted May 5, 2016 Share Posted May 5, 2016 Just musing, if you don't know this off the top of your head, don't bother researching it as I will get to it eventually. More of an unnecessary software trick. Let's say you wanted to use bit 1 as the toggle for RS232 or SD type clock bit and pin 2 as data. Would a sequence like INC PORT DELAY INC PORT DELAY be OK or would it lead to problems down stream,like switching port I/O configuration would still have the count value? Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 6, 2016 Author Share Posted May 6, 2016 Just musing, if you don't know this off the top of your head, don't bother researching it as I will get to it eventually. More of an unnecessary software trick. Let's say you wanted to use bit 1 as the toggle for RS232 or SD type clock bit and pin 2 as data. Would a sequence like INC PORT DELAY INC PORT DELAY be OK or would it lead to problems down stream,like switching port I/O configuration would still have the count value? I'm not sure what that would really do for you. Sure it would toggle Pin 1 (RS232 or a SPI clock line), but the data on pin 2 would simply be a divide-by-2 counter. Is that what you want? Of course I could be missing something . - Michael Quote Link to comment Share on other sites More sharing options...
ricortes Posted May 6, 2016 Share Posted May 6, 2016 Just eliminates the need for a LDA #0 or LDA #1 to set bit state and leaves A reg alone. First inc will set start port state for start bit for example. Next inc or a skip of the inc will set the data bit at a one or zero. Pointless in that saving a couple of bytes or running faster then the port can handle transitions is overkill. I forgot who did it, Maybe Guss or Hias, did a clock chip on a J/S port that used a clock bit. Between that and your hacks, it is enough to get me curious! :} 1 Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 6, 2016 Author Share Posted May 6, 2016 (edited) Just eliminates the need for a LDA #0 or LDA #1 to set bit state and leaves A reg alone. First inc will set start port state for start bit for example. Next inc or a skip of the inc will set the data bit at a one or zero. Pointless in that saving a couple of bytes or running faster then the port can handle transitions is overkill. I forgot who did it, Maybe Guss or Hias, did a clock chip on a J/S port that used a clock bit. Between that and your hacks, it is enough to get me curious! :} Now I see the light . Very interesting way to do that. As for the actual end use I had in mind for the RS232 R:handler code... it was to take the place of the PWM feedback I had added to my Stepper Motor Control Program. Although the PWM to analog feedback worked very well, it was affected by ambient temperature changes as well as other factors that wasn't acceptable for my application. So I needed another method to feed the position data to my PC DasyLab program, and that came in the form of the following code which was altered to put the RS232 TXD bit on joystick port 2, and to not interfere with the motor control chip's (A4988) enable pin while transmitting (leave the chip disabled). 10 ;********************************* 20 ;* R-Handler * 30 ;* JOY PORTA-0 R: DEVICE * 40 ;* Adapted for use with A4988 * 50 ;* stepper motor chip on JOY#1 * 60 ;* * 70 ;* INITIALIZE - BASIC CALL $068F * 80 ;* ML CALL $0690 * 90 ;********************************* 0100 ; 0110 COUNT = $0600 0120 BUFFER = $0601 0130 RSENTRY = $032C 0140 PACTL = $D302 0150 PORTA = $D300 0160 NMIEN = $D40E 0170 DMACTL = $D400 0180 EOL = $9B 0190 CR = $0D 0200 LF = $0A 0210 K = 150 110 & 300 BAUD 0220 L = 6 300 BAUD 0230 ; L=18 FOR 110 BAUD 0240 ; 0250 *=$0602 0260 ; 0270 HANDLTAB 0280 .WORD OPEN-1 0290 .WORD CLOSE-1 0300 .WORD GETBYTE-1 0310 .WORD PUTBYTE-1 0320 .WORD STATUS-1 0330 .WORD SPECIAL-1 0340 .BYTE 0,0,0,0 FILL REST WITH 0 0350 ; 0360 ; THE OPEN ROUTINE 0370 ; 0380 OPEN = * 0390 INIT 0400 LDA #$38 0410 STA PACTL 0420 LDA #$FF ALL BITS = OUT 0430 STA PORTA 0440 LDA #$3C 0450 STA PACTL 0460 LDA #$14 SET TXD = 1 0470 STA PORTA SET A4988 EN = 1 0480 SUCCESS 0490 LDY #1 0500 RTS 0510 ; 0520 ; THE CLOSE DUMMY ROUTINE 0530 ; ONLY RETURN SUCCESS IN Y (1) 0540 ; 0550 CLOSE = SUCCESS 0560 NOTIMPL 0570 LDY #146 RETURN WITH Y=146 0580 RTS 0590 ; 0600 ; THE FOLLOWING COMMANDS ARE 0610 ; NOT IMPLEMENTED SO GET ERROR 0620 ; CODE 146 0630 ; 0640 GETBYTE = NOTIMPL 0650 STATUS = NOTIMPL 0660 SPECIAL = NOTIMPL 0670 ; THE PUTBYTE COMMAND 0680 ; DATA IN ACCU 0690 ; STATUS IN Y (=1) 0700 ; 0710 PUTBYTE 0720 CMP #EOL 0730 BNE NOEOL 0740 ; 0750 ; IF EOL GIVE CRLF TO DEVICE 0760 ; 0770 LDA #CR 0780 JSR SEROUT 0790 LDA #LF 0800 NOEOL 0810 JSR SEROUT 0820 LDY #1 0830 RTS 0840 ; 0850 ; SERIALOUT 0860 ; 0870 SEROUT 0880 STA BUFFER PRESERVE ACC 0890 ; 0900 ; DISABLE INTERRUPTS 0910 ; 0920 SEI 0930 LDA #0 0940 STA NMIEN 0950 STA DMACTL 0960 ; 0970 ; SEND STARTBIT 0980 ; 0990 LDA #$04 TXD = 0 1000 STA PORTA 1010 JSR BITWAIT 1020 ; 1030 ; SEND CHARACTER DATA 1040 ; 1050 LDY #8 1060 STY COUNT 1070 ; 1080 SENDBYTE 1090 LDA BUFFER 1091 ROL A MOVE BIT TO JOY2 1092 ROL A 1093 ROL A 1094 ROL A 1095 ORA #$04 A4988 EN = 1 1100 STA PORTA 1110 ROR BUFFER 1120 JSR BITWAIT 1130 DEC COUNT 1140 BNE SENDBYTE 1150 ; 1160 ; SEND 2 STOPBITS 1170 ; 1180 LDA #$14 TXD = 1 1190 STA PORTA 1200 JSR BITWAIT 1210 JSR BITWAIT 1220 ; 1230 ; ENABLE INTERRUPTS 1240 ; 1250 LDA #$22 1260 STA DMACTL 1270 LDA #$FF 1280 STA NMIEN 1290 CLI 1300 RTS DONE SENDING 1310 ; 1320 ; THE BIT TIMING ROUTINE 1330 ; FOR AN EXACT BAUDRATE 1340 ; 1350 BITWAIT 1360 LDX #K 1370 LOOPK 1380 LDY #L 1390 LOOPL 1400 DEY 1410 BNE LOOPL 1420 DEX 1430 BNE LOOPK 1440 RTS 1450 ; 1460 ; ROUTINE FOR INSTALLING THE 1470 ; RS232 HANDLER 1480 ; 1490 INITHAN 1500 PLA BASIC ENTRY POINT 1510 LDA #'R DEVICE NAME 1520 STA RSENTRY 1530 LDA #HANDLTAB&255 1540 STA RSENTRY+1 1550 LDA #HANDLTAB/256 1560 STA RSENTRY+2 1570 JMP OPEN 1580 .END It works great! I also needed to have my BASIC code break the position number into individual ASCII digits before sending to the R:device, so this subroutine worked quite well for doing that (enter with TEMP = the number you wish to decimalize as I call it). Note: First set-up channel for R:device: OPEN #2,12,0,"R:" 3010 REM <DECIMALIZE ROUTINE> 3020 REM 3030 D3=INT(TEMP/100) 3040 D2=INT((TEMP-(D3*100))/10) 3050 D1=INT((TEMP-(D3*100))-(D2*10)) 3060 PUT #2,D3+48:PUT #2,D2+48:PUT #2,D1+48:PUT #2,13 3070 RETURN Here's the BASIC loader to put the R:handler code into play. 910 REM <LOAD R: HANDLER CODE> 911 FOR AD=1538 TO 1697 912 READ B:POKE AD,B 913 NEXT AD 914 N=USR(1679):REM ** INIT R:HAND ** 915 REM 4000 DATA 17,6,37,6,40,6,43,6 4010 DATA 40,6,40,6,0,0,0,0 4020 DATA 169,56,141,2,211,169,255,141 4030 DATA 0,211,169,60,141,2,211,169 4040 DATA 20,141,0,211,160,1,96,160 4050 DATA 146,96,201,155,208,7,169,13 4060 DATA 32,61,6,169,10,32,61,6 4070 DATA 160,1,96,141,1,6,120,169 4080 DATA 0,141,14,212,141,0,212,169 4090 DATA 4,141,0,211,32,132,6,160 4100 DATA 8,140,0,6,173,1,6,42 4110 DATA 42,42,42,9,4,141,0,211 4120 DATA 110,1,6,32,132,6,206,0 4130 DATA 6,208,233,169,20,141,0,211 4140 DATA 32,132,6,32,132,6,169,34 4150 DATA 141,0,212,169,255,141,14,212 4160 DATA 88,96,162,150,160,6,136,208 4170 DATA 253,202,208,248,96,104,169,82 4180 DATA 141,44,3,169,2,141,45,3 4190 DATA 169,6,141,46,3,76,18,6 The only annoyance, although it's minor, is that data sent to the R:device requires a momentary blanking of the screen DMA. Perhaps in a future version of this routine a way can be worked out to somehow do the timing loops during the horizontal and vertical blank period and not disrupt anything. Also I noticed that Turbo Basic did not like the repetitive DMA disables, and would eventually go crazy with rolling jibberish on screen. Other BASIC's did not do this. And here's a demo of it in action (Atari on the left --- sending RS232 data to --- PC on the right). https://www.youtube.com/watch?v=EAaRgbd5EkA&feature=em-upload_owner - Michael Edited May 6, 2016 by mytekcontrols 2 Quote Link to comment Share on other sites More sharing options...
thorfdbg Posted May 7, 2016 Share Posted May 7, 2016 You just described what I said. The register is read/write, as in it will contain the output setting previously set. So all you need to do if only using 1 or 2 bits is to read the existing value, then use logic instructions to do your own bitsettings without disturbing the others. Actually, no. The story of the PIA is that it has two different ports, port A and B, and they are really electrially different. For one of the ports, a READ on an output register returns the last value written into the output, i.e. it reads from the buffer. I believe this is port A. Port A has tri-state outputs that can drive the output line low or high. Port B is different: It has open collector outputs that can only drive the output low, but requires a pull-up externally to drive it high. If you READ from a port-B output register, it returns the true electrical state on the pin, unbuffered. That is, if you drive the output high, but pull it low externally (which you can do, due to the open collector), then the read will return low, not high. 1 Quote Link to comment Share on other sites More sharing options...
Rybags Posted May 7, 2016 Share Posted May 7, 2016 (edited) OK, I didn't have that info in my datasheets. The Rockwell one seems to have better info than the MOS one http://archive.6502.org/datasheets/rockwell_r6520_pia.pdf But from a programming POV it shouldn't matter as 400/800 has external pullups on all the port bits. For XL/XE PORTB is sort of inconsequential since it's devoted to driving MMU inputs for memory control. Although the Atarimax 32in1 OS does utilize the output of PB7 as a serial data channel to receive commands to enquire or change which OS is active. Edited May 7, 2016 by Rybags Quote Link to comment Share on other sites More sharing options...
+mytek Posted May 7, 2016 Author Share Posted May 7, 2016 (edited) Actually, no. The story of the PIA is that it has two different ports, port A and B, and they are really electrially different. For one of the ports, a READ on an output register returns the last value written into the output, i.e. it reads from the buffer. I believe this is port A. Port A has tri-state outputs that can drive the output line low or high. So basically if I understand this right, any bit of PortA that was set as an output would have it's logic state reflected in the output buffer which is readable. And I would think that should yield the same data as if the outputs were directly readable? I can't think of a situation other than over loading the output pins (forced to GND or to VDD) where this wouldn't be true. Any bits that were set as inputs should still have their logic state read directly, and not be buffered? - Michael Edited May 7, 2016 by mytekcontrols Quote Link to comment Share on other sites More sharing options...
phaeron Posted May 10, 2016 Share Posted May 10, 2016 Other way around -- port A reads (input AND output) for outputs, while port B reads outputs. You can set port A to all outputs with output $FF and still read joystick port 1. 2 1 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.