+Lee Stewart Posted August 22, 2017 Share Posted August 22, 2017 H-m-m-m... I am not having any trouble accessing more than one element in a zero-based array before returning to XB. Let’s have a gander at your code. ...lee Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 Welp, I am still having the same BAD ARGUMENT error as before even when R0 is set to 1... Here's the code. Ignore that it does not actually return to XB yet but just loops around. The 256th element of the array contains the number of valid elements in that array. EDIT: I missed your correction regarding R0, but the issue remains ** XB PIO LOW LEVEL DATA OUT ROUTINE ** ** AUGUST 2017 ** ** BY WALID MAALOULI ** DEF DATOUT PIO EQU >5000 PIO PORT DATA ADDRESS FAC EQU >834A FLOATING POINT ACCUMULATOR ADDRESS XMLLNK EQU >2018 NUMREF EQU >200C REGSTR BSS 8 STORAGE FOR RETURN REGISTERS ** GET NUMBER OF VERTICES DATOUT MOV R11,@REGSTR SAVE RETURN REGISTERS MOV R13,@REGSTR+2 MOV R14,@REGSTR+4 MOV R15,@REGSTR+6 LI R0,256 SELECT 256TH ELEMENT OF VERTEX ARRAY (# OF VERTICES) LI R1,1 SELECT ARGUMENT 1 FROM XB CALL BLWP @NUMREF FETCH ARGUMENT AND PLACE IN FAC BLWP @XMLLNK DATA >12B8 CONVERT VALUE TO INTEGER MOV @FAC,R4 SAVE COUNTER INTO R4 INC R4 ARRAY ZERO BASED. CONVERT TO 1 BASED ** SEND BYTE ARRAY VALUES TO PIO PORT BL @PIOINI INITIALIZE PIO PORT REDO LI R0,1 POINT TO FIRST ELEMENT OF VERTEX ARRAY LI R1,1 SELECT ARGUMENT 1 FROM XB CALL LOOP BLWP @NUMREF FETCH VERTEX BLWP @XMLLNK DATA >12B8 CONVERT TO INTEGER MOVB @FAC+1,@PIO SEND BYTE TO PIO PORT INC R0 POINT TO NEXT VERTEX ARRAY ELEMENT C R0,R4 CHECK IF LAST ELEMENT REACHED JLE LOOP JMP REDO ** INITIALIZE RS232 CARD PIOINI LI R12,>1300 PLACE RS232 CARD CRU ADDRESS IN R12 SBO 0 ACTIVATE CARD SBO 7 TURN CARD LED ON SBZ 1 SET THE PIO PORT TO OUTPUT RT ** RETURN TO XB RETURN MOV @REGSTR,R11 MOV @REGSTR+2,R13 MOV @REGSTR+4,R14 MOV @REGSTR+6,R15 SBZ 0 INACTIVATE RS232 CARD SBZ 7 TURN LED OFF RT END Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 So I tried Anders' suggestion and I'm not having much luck there either unfortunately. XB code: 100 CALL CLEAR 101 CALL INIT :: CALL LOAD("DSK5.PIOOUTA") 105 DIM VERTEX(256),POINT(16,16) ... 330 REM SEND ARRAY TO PIO PORT 350 CALL LINK("ARYLOC",MEMADR) 355 CALL LOAD(MEMADR,VPOINTER) :: MEMADR=MEMADR+1 360 FOR I=0 TO VPOINTER :: CALL LOAD(MEMADR+I,VERTEX(I)) :: NEXT I 370 CALL LINK("DATOUT") 390 GOTO 160 ALC code: ** XB PIO LOW LEVEL DATA OUT ROUTINE ** ** AUGUST 2017 ** ** BY WALID MAALOULI ** DEF DATOUT,ARYLOC PIO EQU >5000 PIO PORT DATA ADDRESS FAC EQU >834A FLOATING POINT ACCUMULATOR ADDRESS XMLLNK EQU >2018 NUMREF EQU >200C NUMASG EQU >2008 REGSTR BSS 8 STORAGE FOR RETURN REGISTERS VERTEX BSS 128 STORAGE FOR VERTICES ** SEND ADDRESS OF VERTICES STORAGE LOCATION IN MEMORY ARYLOC MOV R11,@REGSTR SAVE RETURN REGISTERS MOV R13,@REGSTR+2 MOV R14,@REGSTR+4 MOV R15,@REGSTR+6 CLR @FAC LI R0,VERTEX MOV R0,@FAC PLACE STORAGE ADDRESS IN FAC BLWP @XMLLNK DATA >0020 CONVERT TO FLOATING POINT CLR R0 LI R1,1 SELECT ARGUMENT 1 OF XB CALL BLWP @NUMASG B @RETURN ** SEND ARRAY TO PIO PORT DATOUT MOV R11,@REGSTR SAVE RETURN REGISTERS MOV R13,@REGSTR+2 MOV R14,@REGSTR+4 MOV R15,@REGSTR+6 BL @PIOINI INITIALIZE PIO PORT CLR R3 MOVB @VERTEX,R3 GET NUMBER OF VERTICES IN ARRAY SWPB R3 REDO LI R1,1 LOOP MOVB @VERTEX(R1),@PIO SEND ARRAY BYTE TO PIO INC R1 C R1,R3 JLE LOOP JMP REDO ** INITIALIZE RS232 CARD PIOINI LI R12,>1300 PLACE RS232 CARD CRU ADDRESS IN R12 SBO 0 ACTIVATE CARD SBO 7 TURN CARD LED ON SBZ 1 SET THE PIO PORT TO OUTPUT RT ** RETURN TO XB RETURN MOV @REGSTR,R11 MOV @REGSTR+2,R13 MOV @REGSTR+4,R14 MOV @REGSTR+6,R15 SBZ 0 INACTIVATE RS232 CARD SBZ 7 TURN LED OFF RT END I'm sure I'm missing something here... Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 23, 2017 Share Posted August 23, 2017 I am guessing your Basic program is something like 100 DIM PIO(256) 110 PIO(256) = 256 120 REM 130 REM Set up elements 0..255 with values for DATAOUT 140 REM 150 CALL INIT 160 CALL LOAD("DSK1.DATAOUT") 170 CALL LINK("DATAOUT",PIO()) 180 ... Your ALC to read PIO(256) should work, setting R4 to 256. Subsequently setting R4 to 257 with “INC R4”, however, will read outside your array bounds. You should, in fact, decrement R4 because it is a zero-based array. “REDO LI R0,1” should be “REDO CLR R0” to start at the first element. The loop will now read 256 elements from PIO(0..255). If you change the program to “OPTION BASE 1”, you should change the Basic program to 90 OPTION BASE 1 100 DIM PIO(257) 110 PIO(257) = 256 120 REM 130 REM Set up elements 1..256 with values for DATAOUT 140 REM 150 CALL INIT 160 CALL LOAD("DSK1.DATAOUT") 170 CALL LINK("DATAOUT",PIO()) 180 ... You would now not decrement R4, leaving it at 256. You would also restore the statement, “REDO LI R0,1”. I think that should do it. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 Lee, R4 will contain the number of data elements to read from the array which I save in element 255 in the XB program. Given that you have confirmed that R0 can be 0 for an array starting with a 0 index, then the program will need to be modified back to my original design where R4 is not incremented by 1, and that did not work either (here's the original code) ** XB PIO LOW LEVEL DATA OUT ROUTINE ** ** AUGUST 2017 ** ** BY WALID MAALOULI ** DEF DATOUT PIO EQU >5000 PIO PORT DATA ADDRESS FAC EQU >834A FLOATING POINT ACCUMULATOR ADDRESS XMLLNK EQU >2018 NUMREF EQU >200C REGSTR BSS 8 STORAGE FOR RETURN REGISTERS ** GET NUMBER OF VERTICES DATOUT MOV R11,@REGSTR SAVE RETURN REGISTERS MOV R13,@REGSTR+2 MOV R14,@REGSTR+4 MOV R15,@REGSTR+6 LI R0,255 SELECT 256TH ELEMENT OF VERTEX ARRAY (# OF VERTICES) LI R1,1 SELECT ARGUMENT 1 FROM XB CALL BLWP @NUMREF FETCH ARGUMENT AND PLACE IN FAC BLWP @XMLLNK DATA >12B8 CONVERT VALUE TO INTEGER MOV @FAC,R4 SAVE COUNTER INTO R4 ** SEND BYTE ARRAY VALUES TO PIO PORT BL @PIOINI INITIALIZE PIO PORT. REDO LI R0,0 POINT TO FIRST ELEMENT OF VERTEX ARRAY LI R1,1 SELECT ARGUMENT 1 FROM XB CALL LOOP BLWP @NUMREF FETCH VERTEX BLWP @XMLLNK DATA >12B8 CONVERT TO INTEGER MOVB @FAC+1,@PIO SEND BYTE TO PIO PORT INC R0 POINT TO NEXT VERTEX ARRAY ELEMENT C R0,R4 CHECK IF LAST ELEMENT REACHED JLE LOOP JMP REDO ** INITIALIZE RS232 CARD PIOINI LI R12,>1300 PLACE RS232 CARD CRU ADDRESS IN R12 SBO 0 ACTIVATE CARD SBO 7 TURN CARD LED ON SBZ 1 SET THE PIO PORT TO OUTPUT RT ** RETURN TO XB RETURN MOV @REGSTR,R11 MOV @REGSTR+2,R13 MOV @REGSTR+4,R14 MOV @REGSTR+6,R15 SBZ 0 INACTIVATE RS232 CARD SBZ 7 TURN LED OFF RT END Would you mind posting the code snippet you used to test your access to the array elements? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 23, 2017 Share Posted August 23, 2017 So I tried Anders' suggestion and I'm not having much luck there either unfortunately. XB code: <snip> ALC code: <snip> I'm sure I'm missing something here... I presume you initialized VPOINTER to the number of vertices, which must be less than 128, unless you make the ALC VERTEX array larger than 128 bytes. Also, with the first byte of the array a count byte, you can only address 255 bytes—any larger number takes more than 1 byte to store. Line 360 should start storage at MEMADR+1 to avoid stepping on the vertex count. It should be either 360 FOR I=1 TO VPOINTER :: CALL LOAD(MEMADR+I,VERTEX(I)) :: NEXT I or 360 FOR I=0 TO VPOINTER :: CALL LOAD(MEMADR+I+1,VERTEX(I)) :: NEXT I I think I would change the loop to REDO CLR R3 MOVB @VERTEX,R3 GET NUMBER OF VERTICES IN ARRAY SWPB R3 LI R2,VERTEX+1 LOOP MOVB *R2+,@PIO SEND ARRAY BYTE TO PIO DEC R3 JNE LOOP JMP REDO ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 23, 2017 Share Posted August 23, 2017 (edited) ... Would you mind posting the code snippet you used to test your access to the array elements? ** TEST OF NUMREF FOR ARRAYS ** ** AUGUST 2017 ** ** BY LEE STEWART ** DEF SPIN FAC EQU >834A FLOATING POINT ACCUMULATOR ADDRESS ARG EQU >835C ARGUMENT REGISTER XMLLNK EQU >2018 NUMASG EQU >2008 NUMREF EQU >200C CFI EQU >12B8 CIF EQU >0020 ** SPIN WHILE WE CHECK THE DEBUGGER SPIN CLR R0 LI R1,1 BLWP @NUMREF LI R0,1 BLWP @NUMREF <---just overwrites FAC with second value INCT @FAC CLR R0 BLWP @NUMASG INCT @FAC INC R0 BLWP @NUMASG RT END I called it “SPIN” because that was what I was going to let it do. Instead, I just read the first two elements of the array and added 2 to the second FAC byte and returned that value to the first element, then did it again for the second. Here is the Basic program: 100 CALL INIT 110 CALL LOAD("DSK1.TEST_ARRAY.OBJ") 120 DIM A(10) 130 FOR I = 0 TO 10 140 A(I) = I+1 150 NEXT I 160 CALL LINK("SPIN",A()) 170 FOR I = 0 TO 10 180 PRINT A(I) 190 NEXT I 200 GOTO 200 ...lee Edited August 23, 2017 by Lee Stewart Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 23, 2017 Share Posted August 23, 2017 Lee, R4 will contain the number of data elements to read from the array which I save in element 255 in the XB program. Given that you have confirmed that R0 can be 0 for an array starting with a 0 index, then the program will need to be modified back to my original design where R4 is not incremented by 1, and that did not work either (here's the original code) ... I can't find anything wrong with it—assuming that VERTEX(255) is 254 or less (unless you don't care that it might send the count to @PIO. The only thing besides setting breakpoints in the debugger might be to use your own workspace as Anders suggested. ...lee Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 23, 2017 Share Posted August 23, 2017 Generally, when passing an array like this, it's better to store the number of relevant elements in the first element of the array. If you store that in array(0), then you don't have to know in advance how large the array is. That's good, since it implies that the same assembly routine can handle any size of array. You know that you always have array(0), so you can always look there to find out if there are seven elements in the array, or 389 or whatever. With the byte array method I suggested, you have to send the byte count as a 16-bit value (two bytes), if you need an array larger than 255 bytes. But again, sending the size first will allow you to know how far down the array you should index. Quote Link to comment Share on other sites More sharing options...
RXB Posted August 23, 2017 Share Posted August 23, 2017 This is why TI Basic and TI Extended Basic are better than other Basic Languages. Strings store the SIZE of the String so you use as a index. Other Basics make you count the string to the end to find end of string, huge waste of processing time. Even TI Basic and TI Extended Basic stores the size of numbers also when tokenized i.e. Address:Line#:type:length:token:number stored. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 I presume you initialized VPOINTER to the number of vertices, which must be less than 128, unless you make the ALC VERTEX array larger than 128 bytes. Also, with the first byte of the array a count byte, you can only address 255 bytes—any larger number takes more than 1 byte to store. Line 360 should start storage at MEMADR+1 to avoid stepping on the vertex count. It should be either 360 FOR I=1 TO VPOINTER :: CALL LOAD(MEMADR+I,VERTEX(I)) :: NEXT I or 360 FOR I=0 TO VPOINTER :: CALL LOAD(MEMADR+I+1,VERTEX(I)) :: NEXT I Yes, line 355 of the XB program already does that I think I would change the loop to REDO CLR R3 MOVB @VERTEX,R3 GET NUMBER OF VERTICES IN ARRAY SWPB R3 LI R2,VERTEX+1 LOOP MOVB *R2+,@PIO SEND ARRAY BYTE TO PIO DEC R3 JNE LOOP JMP REDO Lee, what is the benefit in using your loop format as compared to my original one since they both achieve the same thing? Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 Generally, when passing an array like this, it's better to store the number of relevant elements in the first element of the array. If you store that in array(0), then you don't have to know in advance how large the array is. That's good, since it implies that the same assembly routine can handle any size of array. You know that you always have array(0), so you can always look there to find out if there are seven elements in the array, or 389 or whatever. With the byte array method I suggested, you have to send the byte count as a 16-bit value (two bytes), if you need an array larger than 255 bytes. But again, sending the size first will allow you to know how far down the array you should index. I actually did that with your version of the program where the first element of the array is the element count. Question: with the expansion memory on, XB reserves the lower 8K of RAM from >2000 to >3FFF for ALC subroutines. Per my program, the Vertex storage location should be at >2008 (confirmed by creating a list file when assembling), and yet the address returned to XB for it is somewhere in the >2300 range (I'm not at the TI currently and don't have the exact value). When run, the program gets the Vertex address, loads it with the array values, and then just hangs... I need to whip out the debugger tonight and see what the heck is going on here... Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 ** TEST OF NUMREF FOR ARRAYS ** ** AUGUST 2017 ** ** BY LEE STEWART ** DEF SPIN FAC EQU >834A FLOATING POINT ACCUMULATOR ADDRESS ARG EQU >835C ARGUMENT REGISTER XMLLNK EQU >2018 NUMASG EQU >2008 NUMREF EQU >200C CFI EQU >12B8 CIF EQU >0020 ** SPIN WHILE WE CHECK THE DEBUGGER SPIN CLR R0 LI R1,1 BLWP @NUMREF LI R0,1 BLWP @NUMREF <---just overwrites FAC with second value INCT @FAC CLR R0 BLWP @NUMASG INCT @FAC INC R0 BLWP @NUMASG RT END I called it “SPIN” because that was what I was going to let it do. Instead, I just read the first two elements of the array and added 2 to the second FAC byte and returned that value to the first element, then did it again for the second. Here is the Basic program: 100 CALL INIT 110 CALL LOAD("DSK1.TEST_ARRAY.OBJ") 120 DIM A(10) 130 FOR I = 0 TO 10 140 A(I) = I+1 150 NEXT I 160 CALL LINK("SPIN",A()) 170 FOR I = 0 TO 10 180 PRINT A(I) 190 NEXT I 200 GOTO 200 ...lee I'll test out your code tonight. At first look, it does not seem to be doing anything different than what I have been doing... Puzzling... Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 BTW, thanks for all the help guys. It's always nice to be able to pick someone else's noggin when stuck Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 23, 2017 Share Posted August 23, 2017 ... Lee, what is the benefit in using your loop format as compared to my original one since they both achieve the same thing? You are right. I always like countdown loops because it usually makes the compare instruction unnecessary. It only saves one instruction, though. I should have sat on my hands a little longer. ...lee Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 You are right. I always like countdown loops because it usually makes the compare instruction unnecessary. It only saves one instruction, though. I should have sat on my hands a little longer. ...lee Actually saving one instruction could be significant when processing large arrays. I'll keep that in mind Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 23, 2017 Share Posted August 23, 2017 Question: with the expansion memory on, XB reserves the lower 8K of RAM from >2000 to >3FFF for ALC subroutines. Per my program, the Vertex storage location should be at >2008 (confirmed by creating a list file when assembling), and yet the address returned to XB for it is somewhere in the >2300 range (I'm not at the TI currently and don't have the exact value). When run, the program gets the Vertex address, loads it with the array values, and then just hangs... Ehh, this was a long time ago, but doesn't XB also store some data/code in low RAM when you do CALL INIT? Or is that Editor/Assembler only? Quote Link to comment Share on other sites More sharing options...
Willsy Posted August 23, 2017 Share Posted August 23, 2017 Ehh, this was a long time ago, but doesn't XB also store some data/code in low RAM when you do CALL INIT? Or is that Editor/Assembler only? Yes. All the way to >25FF (to my surprise). Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 Ah! OK then that explains the value I got back for the matrix storage address. So that's not the issue... More digging Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted August 23, 2017 Share Posted August 23, 2017 (edited) Yes. All the way to >25FF (to my surprise). When doing CALL INIT XB copies >600 bytes out of GROM, but what is from >2538 to >2600 (and probably a little before that) is just extra stuff. If I remember right, after CALL INIT the value at >2002 is the first free address. The assembly support routines only go from >2000 to the address in >2002. Unlike XB, RXB does not copy those extra bytes. (edit) assembly support routines are from >2000 to >24F4 and the assembly code is loaded starting at >24F4 Edited August 24, 2017 by senior_falcon Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 23, 2017 Author Share Posted August 23, 2017 When doing CALL INIT XB copies >600 bytes out of GROM, but what is from >2538 to >2600 (and probably a little before that) is just extra stuff. If I remember right, after CALL INIT the value at >2002 is the first free address. The assembly support routines only go from >2000 to the address in >2002. Unlike XB, RXB does not copy those extra bytes. So the user ALC routines would start at >2600 then? 1 Quote Link to comment Share on other sites More sharing options...
Willsy Posted August 23, 2017 Share Posted August 23, 2017 So the user ALC routines would start at >2600 then? If that's what >2002 points to, then yeah! See senior's post above Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted August 24, 2017 Share Posted August 24, 2017 After CALL INIT: >2002 = >24F4 >2004 = >4000 So when you start load assembly code it will be loaded starting at >24F4 and the DEF table will be loaded working backwards from >4000 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted August 24, 2017 Author Share Posted August 24, 2017 Quick update: The version based on apersson850's array access method is fully functional now. Actually, it was never broken to start with, but rather the PIO throughput was much lower than I had expected and it was not being adequately picked up by my connected equipment. The culprit was the compare instruction when cycling through the array elements CLR R3 MOVB @VERTEX,R3 GET NUMBER OF VERTICES IN ARRAY SWPB R3 REDO LI R1,1 LOOP MOVB @VERTEX(R1),@PIO SEND ARRAY BYTE TO PIO INC R1 C R1,R3 JLE LOOP JMP REDO At Lee's suggestion, I changed it to a decrementing loop instead, thus eliminating the compare instruction alltogether REDO CLR R3 MOVB @VERTEX,R3 GET NUMBER OF VERTICES IN ARRAY SWPB R3 LI R2,VERTEX+1 LOOP MOVB *R2+,@PIO SEND ARRAY BYTE TO PIO DEC R3 JNE LOOP JMP REDO and now the array is cycled through much faster. I had no idea Compare executed that slowly... At that point, I'm not going to even bother to use the NUMREF utility function given that I will have to issue a BLWP call for each array element in that case, which is going to be even slower. Fascinating... Quote Link to comment Share on other sites More sharing options...
apersson850 Posted August 24, 2017 Share Posted August 24, 2017 (edited) When accessing bytes (MOVB), indexed access is slightly slower than indirect with auto-increment as well. Then INC or DEC and a JMP are roughly like 1½ MOV, but C is like a MOV. So you reduce the loop time to roughly 5/7 by counting downwards instead. Accessing array times one by one will be much slower, that's correct. Perhaps you want the output to cycle through as fast as possible. Otherwise you may have dual arrays, either after each other or interleaved. The second data item could be the duration you want the output to hold the same data. Here's the original function (just slightly modified) GPLWS EQU >83E0 * Bla, bla... LI R5,PIO REDO CLR R3 LI R2,VERTEX MOVB *R2+,@GPLWS+7 GET NUMBER OF VERTICES IN ARRAY LOOP MOVB *R2+,*R5 SEND ARRAY BYTE TO PIO DEC R3 JNE LOOP JMP REDO And here assuming a delay count (byte) follows each data item. GPLWS EQU >83E0 * Bla, bla... LI R5,PIO REDO CLR R3 CLR R4 LI R2,VERTEX MOVB *R2+,@GPLWS+7 GET NUMBER OF VERTICES IN ARRAY LOOP MOVB *R2+,*R5 SEND ARRAY BYTE TO PIO MOVB *R2+,@GPLWS+9 Fetch delay count DELAY DEC R4 JNE DELAY DEC R3 JNE LOOP JMP REDO Edited August 25, 2017 by apersson850 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.