Writing to two memory address sequentially

JMP $FCE2
jrubin
Member
Member
Posts: 58
Joined: Sun Jun 29, 2014 8:00 pm
Location: Florida

Writing to two memory address sequentially

Post by jrubin » Sat Jul 12, 2014 4:59 am

Im writing to two memory address sequentially, pressing a key will return two bytes from the radio (data from radio memory $0057 and $0058), which are printed to the screen correctly so i know im getting back both, however I want to take those two bytes and load them into $c008 and $c009 as it pulls it from the receive buffer. It only seems to put in the second byte into the memory location.

What im trying to do takes place in RECVBYTE,transfering recvcount value from A to X and using it to augment the memory location (getbyte,x)


SENDBYTE:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;SPECIAL CODE AREA TO SEND PACKET IN A LOOP FROM THE DATA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;AT THE BOTTOM AT GETEEPROM:
ldx #$00
PTTLOOP:
lda GETEEPROM,x
tay ;remember byte to be transmitted
TESTACIA5:
lda status
and #%00010000
beq TESTACIA5 ;wait for bit #4 to be set
sty data ;give byte to ACIA
inx
cpx #$05
bne PTTLOOP
rts


RECVBYTE: ;fetches a byte from the receive buffer.
lda recvcount ;count of bytes in receive buffer
tax
beq RECVEMPTY ;buffer is empty, indicate to caller
ldy rhead ;pointer to start of buffer
lda (rbuff),y ;fetch byte out of buffer into 'A' register
sta getbyte,x ;location of getbyte is $c008
inc rhead ;point to next slot in buffer
dec recvcount ;and add one to count of bytes in buffer
clc ;indicate that we have a character
rts ;return to your program

RECVEMPTY:
sec ;or whatever flag your program uses to tell that the receive buffer was empty
rts ;and return

TERMINAL:
jsr RECVBYTE ;see if there is a received byte in the recv buffer
bcs TERMTRYSEND ;if not, continue
jsr $FFD2 ;if received byte, print it to the screen (CHROUT)

TERMTRYSEND:
jsr $FFE4 ;try to get a character from the keyboard (GETIN)
cmp #$00 ;was there a keystroke available?
beq TERMINAL ;no--go back to top of polling loop
; cmp #$03 ;check for STOP key
; beq TERMEXIT ; exit if pressed
; jsr $FFD2
jsr SENDBYTE ;have char--put it into the transmit buffer and then
jmp TERMINAL ; go back to top of polling loop

TRANSMIT_BUFFER = *+0
RECEIVE_BUFFER = *+256

PTT:
.byte $00,$00,$00,$00,$08

GETEEPROM:
.byte $00,$57,$00,$00,$BB



satpro

Re: Writing to two memory address sequentially

Post by satpro » Sat Jul 12, 2014 8:51 am

Hi jrubin,

Could you post some more information, maybe the entire listing if there's more?

1. The labels --> status, data, recvcount, rbuff, and rhead don't seem like they are defined anywhere, but are used in the source. PTT does not appear to be used by anything. What is the label for $57-58?
2. RECEIVE_BUFFER appears to have a size of 0 bytes, while TRANSMIT_BUFFER is 256 bytes in size.
3. Calling $FFE4 returns either a keypress (ascii code) or 0 in .A, so the cmp #0 instruction can come out.
4. recvcount doesn't seem to be initialized anywhere so its value could be anything.

I think there might be a couple of other things (the loop design, use index registers instead of memory in the loops), but the items listed above should be addressed first. We'll get you fixed up, don't sweat it. :) I'm having a little trouble figuring it out without those labels above are for.

When posting assembly source you can highlight the source text and click on the "Select Code" dropdown box, then click on Assembly. It will display the source text in a mono-spaced font. It is very easy to read then.

dudz
Member
Member
Posts: 140
Joined: Tue Jun 17, 2014 5:40 am

Re: Writing to two memory address sequentially

Post by dudz » Sat Jul 12, 2014 1:58 pm

Code: Select all

TRANSMIT_BUFFER = *+0
RECEIVE_BUFFER = *+256
PTT:
.byte $00,$00,$00,$00,$08
GETEEPROM:
.byte $00,$57,$00,$00,$BB
this is probably not what you intended... notice that assigning a value to a label does not actually reserve any memory, meaning in this case the bytes defined after PTT and GETEEPROM will be in the TRANSMIT_BUFFER area (and anything that comes after it too!). instead you should move the program counter accordingly, like this:

Code: Select all

TRANSMIT_BUFFER = *+0
RECEIVE_BUFFER = *+256
* = * + (2*256) ; move program counter behind RECIEVE_BUFFER
PTT:
.byte $00,$00,$00,$00,$08
GETEEPROM:
.byte $00,$57,$00,$00,$BB

jrubin
Member
Member
Posts: 58
Joined: Sun Jun 29, 2014 8:00 pm
Location: Florida

Re: Writing to two memory address sequentially

Post by jrubin » Sat Jul 12, 2014 2:27 pm

Sorry I didnt send all of the code, this should straighten out some of the confusion.

Would it make more sense to push it to the stack and move it afterwards?

program starts on sys 8192

Code: Select all

base  	    =    $DE00    ;base ACIA address
data  	    =    base
status   	    =    base+1
command    =    base+2
control  	    =    base+3
getbyte         =    $C008


rhead    	    =   $A7      ;pointer to next byte to be removed from receive buffer
rtail    	    =   $A8      ;pointer to location to store next byte received
rbuff     	    =   $F7      ;receive-buffer vector
thead   	    =   $A9      ;pointer to next byte to be removed from transmit buffer
ttail    	    =   $AA      ;pointer to location to store next byte in transmit buffer
tbuff  	    =   $F9      ;transmit buffer

xmitcount 	    =   $AB      ;count of bytes remaining in transmit (xmit) buffer
recvcount     =   $B4      ;count of bytes remaining in receive buffer
errors           =   $B5      ;DSR, DCD, and received data errors information

xmiton   	    =   $B6      ;storage location for model of command register which turn both receive and transmit interrupts on
xmitoff  	    =   $BD      ;storage location for model of command register which turns the receive interrupt on and the
                      		      ;transmit interrupts off

NMINV     =   $0318    ;Commodore Non-Maskable Interrupt vector
OLDVEC    =   $03fe    ;innocuous location to store old NMI vector (two bytes)

;Call the following code as part of system initialization.
;clear all buffer pointers, buffer counters, and errors location
      *=  $2000      ;change to suit your needs
      lda   #$00
      sta   rhead
      sta   rtail
      sta   thead
      sta   ttail
      sta   xmitcount
      sta   recvcount
      sta   errors

;store the addresses of the buffers in the zero-page vectors
      lda   #<TRANSMIT_BUFFER
      sta   tbuff
      lda   #>TRANSMIT_BUFFER
      sta   tbuff + 1
      lda   #<RECEIVE_BUFFER
      sta   rbuff
      lda   #>RECEIVE_BUFFER
      sta   rbuff + 1
      
;load control values     
      lda   #%10011100
      sta   control
;load command values      
      lda   #%00001001
      sta   command
      
      sta   xmitoff     ;store as a model for future use
      and   #%11110000 ;mask off interrupt bits, keep parity/echo bits
      ora   #%00000101 ;and set bits to enable both transmit and receive interrupts
      sta   xmiton      ;store also for future use      
      
NEWVEC:
      sei               ;A stray IRQ shouldnt cause any problems while were changing the NMI vector     
      lda   NMINV      ;get low byte of present vector
      sta   OLDVEC     ;and store it for future use
      lda   NMINV+1    ;do the same
      sta   OLDVEC+1   ;with the high byte
                       ;come here from the SEI if you're not saving
                       ;the old vector
      lda   #<NEWNMI   ;get low byte of new NMI routine
      sta   NMINV      ;store in vector
      lda   #>NEWNMI   ;and do the same with
      sta   NMINV+1    ;the high byte
      cli              ;allow IRQs again     
      
       jmp   TERMINAL   ;go to the example dumb-terminal subroutine  
      
NEWNMI:
     sei              ;the Kernal routine already does this before jumping
                       ;through the NMINV vector
      pha              ;save A register
      txa
      pha              ;save X register
      tya
      pha              ;save Y register       
      
      
      lda   status

;Now prevent any more NMIs from the ACIA

      ldx   #%00000011   ;disable all interrupts, bring RTS inactive, and leave DTR active
      stx   command       ;send to ACIA-- code at end of interrupt handler will re-enable interrupts

;Store the status-register data only if needed for error checking.
;The next received byte will clear the error flags.

      sta   errors        ;only if error checking implemented
      and   #%00011000   ;mask out all but transmit and receive interrupt indicators
      beq   TEST_DCD_DSR

RECEIVE:                  ;process received byte
      and   #%00001000   ;mask all but bit #3
      beq   XMITCHAR      ;if not set, no received byte - if youre using a transmit buffer, the interrupt must have been
                                       ;caused by transmit.  So, branch to handle.
      lda   data          ;get received byte
      ldy   rtail         ;index to buffer
      sta   (rbuff),y     ;and store it
      inc   rtail         ;move index to next slot
      inc   recvcount     ;increment count of bytes in receive buffer (if used by your program)  
       
XMIT:
      lda   xmitcount     ;if not zero, characters still in buffer fall through to process xmit buffer
      beq   TEST_DCD_DSR  ;no characters in buffer-- go to next check
       
XMITBYTE:
      lda   status        ;test bit #4
      and   #%00010000
      beq   TEST_DCD_DSR  ;skip if transmitter still busy

XMITCHAR:                 ;transmit a character
      ldy   thead
      lda   (tbuff),y     ;get character at head of buffer
      sta   data          ;place in ACIA for transmit

                          ;point to next character in buffer
      inc   thead         ;and store new index
      dec   xmitcount     ;subtract one from count of bytes in xmit buffer
      lda   xmitcount
      beq   TEST_DCD_DSR 
       
      lda   xmiton        ;model to leave both interrupts enabled
                                ;If you don't use DCD or DSR
      bne   NMICOMMAND    ;branch always to store model in command register   

TEST_DCD_DSR:
       
NMIEXIT:
      lda   xmitoff       ;load model to turn transmit interrupts off
;and this line sets the interrupt status to whatever is in the 'A' register.

NMICOMMAND:
      sta   command 
      
EXITINT:                  ;restore things and exit
      pla                 ;restore 'Y' register
      tay
      pla                 ;restore 'X' register
      tax
      pla                 ;restore 'A' register      
      
;If you want to continue processing the interrupt with the Kernal routines,
      jmp   (OLDVEC)      ;continue processing interrupt with Kernal handler      
;      
;NOTHING:
;      lda   #$00     ;or whatever flag your program uses to tell that the byte was not transmitted
;      rts                 ;and return  
      
SENDBYTE:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;SPECIAL CODE AREA TO SEND PACKET IN A LOOP FROM THE DATA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;AT THE BOTTOM AT PTT:
ldx #$00
PTTLOOP:
lda GETEEPROM,x
     tay                 ;remember byte to be transmitted
TESTACIA5:
     lda   status
     and   #%00010000
     beq   TESTACIA5      ;wait for bit #4 to be set
     sty   data          ;give byte to ACIA
inx
cpx #$05
bne PTTLOOP
rts

  
RECVBYTE:                 ;fetches a byte from the receive buffer.                      
      lda   recvcount     ;count of bytes in receive buffer
      tax
      beq   RECVEMPTY     ;buffer is empty, indicate to caller
      ldy   rhead         ;pointer to start of buffer
      lda   (rbuff),y     ;fetch byte out of buffer into 'A' register
      sta getbyte,x     ;location of getbyte is $c008
      inc   rhead         ;point to next slot in buffer
      dec   recvcount     ;and add one to count of bytes in buffer
      clc                 ;indicate that we have a character
      rts                 ;return to your program

RECVEMPTY:
      sec                 ;or whatever flag your program uses to tell that the receive buffer was empty
      rts                 ;and return  
          
TERMINAL:
      jsr   RECVBYTE      ;see if there is a received byte in the recv buffer
      bcs   TERMTRYSEND   ;if not, continue 
      jsr   $FFD2         ;if received byte, print it to the screen (CHROUT)

TERMTRYSEND:
      jsr   $FFE4         ;try to get a character from the keyboard (GETIN)
      cmp   #$00          ;was there a keystroke available?
      beq   TERMINAL      ;no--go back to top of polling loop
;      cmp   #$03          ;check for STOP key
;      beq   TERMEXIT      ;  exit if pressed
;      jsr $FFD2
      jsr   SENDBYTE      ;have char--put it into the transmit buffer and then
      jmp   TERMINAL      ;  go back to top of polling loop

TRANSMIT_BUFFER = *+0
RECEIVE_BUFFER  = *+256

PTT:
.byte $00,$00,$00,$00,$08

GETEEPROM:
.byte $00,$57,$00,$00,$BB
    
      
      

jrubin
Member
Member
Posts: 58
Joined: Sun Jun 29, 2014 8:00 pm
Location: Florida

Re: Writing to two memory address sequentially

Post by jrubin » Sun Jul 13, 2014 3:41 pm

Heres a few sections of code running step by step

Code: Select all

;store the addresses of the buffers in the zero-page vectors
      lda   #<TRANSMIT_BUFFER
      sta   tbuff
      lda   #>TRANSMIT_BUFFER
      sta   tbuff + 1
      lda   #<RECEIVE_BUFFER
      sta   rbuff
      lda   #>RECEIVE_BUFFER
      sta   rbuff + 1

this is from the bottom of the program, i put it here for reference

Code: Select all

TRANSMIT_BUFFER = *+0
RECEIVE_BUFFER  = *+256

Code: Select all

.C:2010  A9 DA       LDA #$DA       - A:00 X:00 Y:0A SP:f2 ..-...Z.    5503706
(C:$2010) 
.C:2012  85 F9       STA $F9        - A:DA X:00 Y:0A SP:f2 N.-.....    5503708
(C:$2012) 
.C:2014  A9 20       LDA #$20       - A:DA X:00 Y:0A SP:f2 N.-.....    5503711
(C:$2014) 
.C:2016  85 FA       STA $FA        - A:20 X:00 Y:0A SP:f2 ..-.....    5503713
(C:$2016) 
.C:2018  A9 DA       LDA #$DA       - A:20 X:00 Y:0A SP:f2 ..-.....    5503716
(C:$2018) 
.C:201a  85 F7       STA $F7        - A:DA X:00 Y:0A SP:f2 N.-.....    5503718
(C:$201a) 
.C:201c  A9 21       LDA #$21       - A:DA X:00 Y:0A SP:f2 N.-.....    5503721
(C:$201c) 
.C:201e  85 F8       STA $F8        - A:21 X:00 Y:0A SP:f2 ..-.....    5503723
(C:$201e) 

What is this value $DA and why is it going to F9 (transmit buffer)
then it loads value from transmit buffer again and gets $20

it loads the same values into the receive buffer

dudz
Member
Member
Posts: 140
Joined: Tue Jun 17, 2014 5:40 am

Re: Writing to two memory address sequentially

Post by dudz » Sun Jul 13, 2014 4:50 pm

err... you wrote that code, shouldnt you know what it is doing? $da is the low byte of the buffers address. and since they are one page apart the lowbyte is the same for both.

satpro

Re: Writing to two memory address sequentially

Post by satpro » Sun Jul 13, 2014 5:10 pm

Hi jrubin,

I have never worked with RS-232 programming, but have meddled some with clearing buffers, and I will admit I have not tried to step through this in VICE. But just by looking at it -- a variable like recvcount is always going to hold a value of +1 of whatever your index is (unless it is 0). That is, if the count is 1 then it should be decremented so that it points to byte #0 for retrieval of the first byte in the buffer. I'm wondering if this has anything to do with what is going on.

Also, and this is nothing major, but a simple re-ordering at the top of the routine can save a couple of cycles:

Code: Select all

RECVBYTE:                 ;fetches a byte from the receive buffer.                      
      lda   recvcount     ;count of bytes in receive buffer
      tax
      beq   RECVEMPTY     ;buffer is empty, indicate to caller
can be changed to:

Code: Select all

RECVBYTE:                 ;fetches a byte from the receive buffer.                      
      lda   recvcount     ;count of bytes in receive buffer
      beq   RECVEMPTY     ;buffer is empty, indicate to caller
      tax
This will exit immediately if the count = 0.

The other thing (again, nothing major) is the cmp #0 after JSR $FFE4. That can come out because GETIN returns a 0 if there is nothing pressed so the BEQ by itself will pick that up. (- JSR $FFE4/BEQ -)

Are bytes constantly streaming in? If so, then it seems like the NMI is going to mess up the buffer (and the pointers) because the NMI itself can't be disabled. I would think you have to delay receiving bytes in the NMI itself until the buffer is cleared (until recvcount = 0). The whole getting RS-232 bytes from a buffer via keypress thing seems like it would be prone to big problems. This is just an uneducated guess, though.

Keep working at it. You'll get it. I'll keep checking in (RS-232 is not exactly my strong suit).

jrubin
Member
Member
Posts: 58
Joined: Sun Jun 29, 2014 8:00 pm
Location: Florida

Re: Writing to two memory address sequentially

Post by jrubin » Sun Jul 13, 2014 6:24 pm

satpro wrote:Hi jrubin,

I have never worked with RS-232 programming, but have meddled some with clearing buffers, and I will admit I have not tried to step through this in VICE. But just by looking at it -- a variable like recvcount is always going to hold a value of +1 of whatever your index is (unless it is 0). That is, if the count is 1 then it should be decremented so that it points to byte #0 for retrieval of the first byte in the buffer. I'm wondering if this has anything to do with what is going on.

Also, and this is nothing major, but a simple re-ordering at the top of the routine can save a couple of cycles:

Code: Select all

RECVBYTE:                 ;fetches a byte from the receive buffer.                      
      lda   recvcount     ;count of bytes in receive buffer
      tax
      beq   RECVEMPTY     ;buffer is empty, indicate to caller
can be changed to:

Code: Select all

RECVBYTE:                 ;fetches a byte from the receive buffer.                      
      lda   recvcount     ;count of bytes in receive buffer
      beq   RECVEMPTY     ;buffer is empty, indicate to caller
      tax
This will exit immediately if the count = 0.

The other thing (again, nothing major) is the cmp #0 after JSR $FFE4. That can come out because GETIN returns a 0 if there is nothing pressed so the BEQ by itself will pick that up. (- JSR $FFE4/BEQ -)

Are bytes constantly streaming in? If so, then it seems like the NMI is going to mess up the buffer (and the pointers) because the NMI itself can't be disabled. I would think you have to delay receiving bytes in the NMI itself until the buffer is cleared (until recvcount = 0). The whole getting RS-232 bytes from a buffer via keypress thing seems like it would be prone to big problems. This is just an uneducated guess, though.

Keep working at it. You'll get it. I'll keep checking in (RS-232 is not exactly my strong suit).



Genuis!!! That looks like the issue, the receieve buffer shouldnt have been incremented by 1, it cuts off the first received byte!!! only tx should be padded.

Its not reliable though, i think ive got too much going on in between the code

jrubin
Member
Member
Posts: 58
Joined: Sun Jun 29, 2014 8:00 pm
Location: Florida

Re: Writing to two memory address sequentially

Post by jrubin » Sun Jul 13, 2014 7:06 pm

ive tried both ways and found then equally reliable so im no further than I started.

the command $FFD2 in the TERMINAL: always prints both bytes to the scewwn with no issue, I think I just need some viable way of storing A to memry different than what I am doing

jrubin
Member
Member
Posts: 58
Joined: Sun Jun 29, 2014 8:00 pm
Location: Florida

Re: Writing to two memory address sequentially

Post by jrubin » Sun Jul 13, 2014 7:40 pm

I always get 2 bytes back so I just simplified the code, this works error free and is reliable, ill move these two bytes to zero page FB and FC to work on and dump the results to c000

Code: Select all

RECVBYTE:                 ;fetches a byte from the receive buffer.                      
      lda   recvcount     ;count of bytes in receive buffer
      beq   RECVEMPTY     ;buffer is empty, indicate to caller

      ldy   rhead         ;pointer to start of buffer
      lda   (rbuff),y     ;fetch byte out of buffer into 'A' register
      sta   $C000     ;location of getbyte is $c008
      jsr $ffd2
      inc   rhead         ;point to next slot in buffer
      dec   recvcount     ;and add one to count of bytes in buffer

       ldy   rhead         ;pointer to start of buffer  
      lda   (rbuff),y     ;fetch byte out of buffer into 'A' register
      sta   $C001     ;location of getbyte is $c008
      jsr $ffd2
      inc   rhead         ;point to next slot in buffer
      dec   recvcount     ;and add one to count of bytes in buffer
      clc                 ;indicate that we have a character
      rts                 ;return to your program

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 1 guest