Jump to content
IGNORED

Serial port control with RXB


Vorticon

Recommended Posts

Vorticon, on 08 Feb 2017 - 11:38 PM, said:

Another weird thing: changing the stop bit count in the control register has absolutely no effect on the communication, either emission or reception... Something really fishy is going on here.

 

I'm not sure you'll see an effect anyway in your application. I think the number of stop bits is only relevant if you are transmitted at the max rate, with a start bit immediately following the specified number of stop bits, which effectively provide 'padding' between the characters. A stop bit is a '1', which is also the 'idle state' of the line when no character is being transmitted.

Link to comment
Share on other sites

 

I'm not sure you'll see an effect anyway in your application. I think the number of stop bits is only relevant if you are transmitted at the max rate, with a start bit immediately following the specified number of stop bits, which effectively provide 'padding' between the characters. A stop bit is a '1', which is also the 'idle state' of the line when no character is being transmitted.

 

I only seem to have an issue with reception, not transmission. I am getting data back appropriately, but I can't figure out why the msb is getting set (CRU 7). Nothing I have read so far demonstrates a condition where that bit is set continuously in the receive buffer. Changing the baud rate changes the combination of bits being set which remain constant for that specific baud rate.

 

All that is happening is that a byte is showing up at the Rx line on the TI and it is being put into the reception register and that register is getting corrupted. The Xbees have been configured to 8N1 with no control protocol, so it should be a pure direct transmission Tx to Rx. I tried using TELCO to verify the reception of the byte, but it did not work because I think it is expecting some form of handshake to occur first.

 

Tomorrow I'm going to hook up my logic analyzer to the Ti's Rx line and see what the heck is coming through... Also another test is to introduce a delay on the Arduino side prior to sending the response. Since we are using GPL here and not assembly, it is possible that things are just happening too fast.

Link to comment
Share on other sites

I've not followed this from the beginning, but I have to ask, are you using an RS-232 in the P-Box... or are you attempting this with a NanoPEB?

I'm using an RS232 card with the HDX modification, although the HDX is currently inactivated via a switch.

I already have a CF7+ device and I see no point in getting a NanoPEB as well...

  • Like 1
Link to comment
Share on other sites

Okay, good to know, because Telco will not work with a NanoPEB no matter what you do, so yeah, currently there no point even, if you did not already have a CF7. If you have the interrupt switched back on like you said, I have no clue why it's not working. Let us know what it is when you figure it out, I'm sure I'm not the only one interested in why it's flaky.

Link to comment
Share on other sites

All that is happening is that a byte is showing up at the Rx line on the TI and it is being put into the reception register and that register is getting corrupted. The Xbees have been configured to 8N1 with no control protocol, so it should be a pure direct transmission Tx to Rx. I tried using TELCO to verify the reception of the byte, but it did not work because I think it is expecting some form of handshake to occur first.

 

Huh, that is weird. I don't remember ever doing anything weird to receive characters on the RS232 port (from assembly). It sounds like framing problems, but that should be handled in the hardware. Although it's worth noting that you should get character back on Telco, but unless you are using an 8-bit terminal emulation like ANSI, you won't see characters with the high bit set (I think, that one's been a while).

 

Logic analyzer will at least help rule out the input signal, so it sounds like a good path if you don't have anything else handy that can generate a serial line, but also might be worth trying from the PC if you have a serial port on there?

Link to comment
Share on other sites

 

Tomorrow I'm going to hook up my logic analyzer to the Ti's Rx line and see what the heck is coming through... Also another test is to introduce a delay on the Arduino side prior to sending the response. Since we are using GPL here and not assembly, it is possible that things are just happening too fast.

 

Logic analyser seems to be a good way to go.

 

Just to point out another useful feature of the 9902 - CRU bit 15 enables you to test the state of the RIN (Receive In) pin directly. So using assembly (for the necessary speed), you could test bit 15 and wait until it goes low (indicating the start of a start bit), wait half a serial bit period, then sample each of the serial bits directly. You could then see exactly what is coming down the line, rather than what the 9902 is loading into the receive register. You'd need to do a bit of experimentation with timing loops to get the right values for the Baud rate you're using. The TIBUG monitor uses this technique to autodetect the Baud rate of your terminal: you power on then press a key for a character where the MSB is a '1'. The code measures the width of the start bit in a timing loop, then looks up the loop count in a small lookup table that gives the transmit/receive rate register values to load for that Baud rate.

  • Like 1
Link to comment
Share on other sites

 

Huh, that is weird. I don't remember ever doing anything weird to receive characters on the RS232 port (from assembly). It sounds like framing problems, but that should be handled in the hardware. Although it's worth noting that you should get character back on Telco, but unless you are using an 8-bit terminal emulation like ANSI, you won't see characters with the high bit set (I think, that one's been a while).

 

Logic analyzer will at least help rule out the input signal, so it sounds like a good path if you don't have anything else handy that can generate a serial line, but also might be worth trying from the PC if you have a serial port on there?

 

The numbers I'm sending from the Arduino do not correspond to ASCII characters. I'm going to modify the Arduino code and have it send characters instead. And yes, I will try and use a PC terminal to test as well, but it's more fun to use a logic analyzer! :grin:

Link to comment
Share on other sites

 

Logic analyser seems to be a good way to go.

 

Just to point out another useful feature of the 9902 - CRU bit 15 enables you to test the state of the RIN (Receive In) pin directly. So using assembly (for the necessary speed), you could test bit 15 and wait until it goes low (indicating the start of a start bit), wait half a serial bit period, then sample each of the serial bits directly. You could then see exactly what is coming down the line, rather than what the 9902 is loading into the receive register. You'd need to do a bit of experimentation with timing loops to get the right values for the Baud rate you're using. The TIBUG monitor uses this technique to autodetect the Baud rate of your terminal: you power on then press a key for a character where the MSB is a '1'. The code measures the width of the start bit in a timing loop, then looks up the loop count in a small lookup table that gives the transmit/receive rate register values to load for that Baud rate.

 

This would be my last ditch effort if all else fails, but definitely something to consider.

I did add a transmission delay on the Arduino side (1sec), and it made no difference, so it looks like RXB is able to keep up.

  • Like 1
Link to comment
Share on other sites

Well, here is the result of my testing so far, and unfortunately I am still no closer to solving this issue...

 

I attached my logic analyzer to the XBees, and checked the binary stream on both ends. To recap, when I send an A from the TI, the Arduino responds with 255 and sends it via the XBee back to the TI. B sends a 1 and C sends a 0. In the images below, each division represents one bit of data sent in time.

 

post-25753-0-38796400-1486844470_thumb.jpg

A sent. The response is essentially just the start bit since 255 is binary 11111111.

 

post-25753-0-12081500-1486844480_thumb.jpg

B sent. Here we get the start bit, a one, then all zeros.

 

post-25753-0-83594800-1486844491_thumb.jpg

C sent. Here we have the start bit and all zeros.

 

So clearly the Arduino is sending the right data and XBees are faithfully transmitting that data.

 

So next I hooked up the set up to my laptop via a serial to USB adapter and used HTERM to view the binary stream. A simple terminal program will not work as it can only display ASCII characters. Here again it looks like the PC is receiving the data appropriately with 255, 1 and 0 received.

 

post-25753-0-84103900-1486844515_thumb.jpg

 

Basically then this leaves the issue squarely with the TI. Why am I getting corruption of the receive register? The only difference between the physical setup of the TI and PC is the use of a null modem adapter on the TI side.

 

Any thoughts?

Link to comment
Share on other sites

Vorticon, on 11 Feb 2017 - 8:29 PM, said:Vorticon, on 11 Feb 2017 - 8:29 PM, said:

 

Any thoughts?

 

Have you only tried it with RXB so far? I'd try it in assembly - you could adapt the code I posted earlier (just send a 'fixed' character and see what comes back). May be a bug in RXB, or you haven't got the CALL IO parameters quite right.

 

*** BUT FIRST! ***

 

In your code, add a new line 55 to set CRU bit 13 to zero. See what happens ...

Edited by Stuart
  • Like 3
Link to comment
Share on other sites

 

Have you only tried it with RXB so far? I'd try it in assembly - you could adapt the code I posted earlier (just send a 'fixed' character and see what comes back). May be a bug in RXB, or you haven't got the CALL IO parameters quite right.

 

*** BUT FIRST! ***

 

In your code, add a new line 55 to set CRU bit 13 to zero. See what happens ...

 

Well I'll be damned! It worked! But how??? CRU bit 13 is supposed to be an input only bit indicating the arrival of the first bit of data, at least per Thierry's site. What exactly am I doing when I write to it? Heck it never even occurred to me that I could even do that...

  • Like 2
Link to comment
Share on other sites

You'll have to wait until tomorrow for that as it requires a little explanation. It's late, and a warm bed awaits me. ;-) It will also give me a chance to ponder why you had trouble receiving, as it now looks like you should have had trouble transmitting, :?

 

Will do :) Yeah transmission never seemed to be an issue...

Now I know why I stick with the parallel port any chance I get!

  • Like 1
Link to comment
Share on other sites

 

This would be my last ditch effort if all else fails, but definitely something to consider.

I did add a transmission delay on the Arduino side (1sec), and it made no difference, so it looks like RXB is able to keep up.

LOL this had me worried I might have to fix this issue!

Link to comment
Share on other sites

 

Doing a soft reset on with CRU 31 and making RTS low with CRU 16 did the trick! It works now perfectly! Thanks Stuart!

 

Here's the updated test code:

10 CALL CLEAR
20 CRU=2464 !CRU ADDRESS OF THE FIRST TMS9902 CHIP DIVIDED BY 2
30 CALL IO(3,1,2432,1) !ACTIVATE THE RS232 CARD
35 CALL IO(3,1,CRU+31,1) !RESET TMS9902
40 CALL IO(3,1,CRU+14,1) !SELECT CONTROL REGISTER
50 CALL IO(3,8,CRU,203) !8N1 @ 3MHZ
60 CALL IO(3,1,CRU+12,1) !SELECT RECEPTION RATE REGISTER
70 CALL IO(3,11,CRU,0,39) !9600 BPS
80 CALL IO(3,1,CRU+11,1) !SELECT EMISSION RATE REGISTER
90 CALL IO(3,11,CRU,0,39) !9600 BPS
100 FOR I=11 TO 14::CALL IO(3,1,CRU+I,0)::NEXT I !ENABLE EMIT REGISTER
110 PRINT "READY FOR INPUT"
120 CALL KEY(0,K,S)::IF S=0 THEN 120 !WAIT FOR KEYPRESS
130 PRINT K::CALL IO(3,8,CRU,K) !LOAD EMIT REGISTER
135 CALL IO(3,1,CRU+16,1) !SEND BYTE TO SERIAL PORT
140 GOTO 120

Not to be picky but you could change line 120 to:

 

120 CALL KEY("",0,K,S) ! WAIT FOR KEYPRESS

 

RXB has a built in:

IF K="VALUE" THEN NEXT ELSE LOOP

 

Example:

CALL KEY("X",0,K,S) ! Will loop forever till the X key is pressed

CALL KEY("",0,K,S) ! Will loop forever til any key is pressed

  • Like 1
Link to comment
Share on other sites

Not to be picky but you could change line 120 to:

 

120 CALL KEY("",0,K,S) ! WAIT FOR KEYPRESS

 

RXB has a built in:

IF K="VALUE" THEN NEXT ELSE LOOP

 

Example:

CALL KEY("X",0,K,S) ! Will loop forever till the X key is pressed

CALL KEY("",0,K,S) ! Will loop forever til any key is pressed

 

Oh nice! Good to know. Thanks for pointing that out.

  • Like 1
Link to comment
Share on other sites

Vorticon, on 12 Feb 2017 - 12:20 AM, said:Vorticon, on 12 Feb 2017 - 12:20 AM, said:Vorticon, on 12 Feb 2017 - 12:20 AM, said:

 

Well I'll be damned! It worked! But how??? CRU bit 13 is supposed to be an input only bit indicating the arrival of the first bit of data, at least per Thierry's site. What exactly am I doing when I write to it? Heck it never even occurred to me that I could even do that...

 

So here's what I think is happening. There are a couple of points that I don't fully understand, but you seem to have a working solution. ;-) Also, you're better off looking at the TI data manual for this (ftp://ftp.whtech.com/datasheets%20and%20manuals/Datasheets%20-%20TI/TMS9902A.pdf) - it has tables covering all the input and output CRU bits, and Thierry's site doesn't cover everything.

 

I'll refer to your code listing back in post #24.

 

There are a number of registers available for programming:

 

(1) Control Register - you select this for loading by writing a 1 to CRU bit 14.

(2) Interval Register - selected for loading by writing a 1 to CRU bit 13.

(3) Receive Data Rate Register - selected for loading by writing a 1 to CRU bit 12.

(4) Transmit Data Rate Register - selected for loading by writing a 1 to CRU bit 11.

 

You quite correctly selected and loaded registers 1, 3 and 4 in your code, lines 40 - 90. You load the register by writing one or more bits to CRU bits 10 - 0.

 

We then added a soft reset of the 9902 in line 35. One effect of this is that it sets CRU bits 14 - 11 all to 1 - it selects *all* the registers for loading. So what happens in this condition? When you write to CRU bits 10 - 0, it writes to the first register that is selected using the priority order listed above. So with all the registers selected, the first write will be to the Control Register (which then deselects itself), the next write to the Interval Register, then the Receive Data Rate Register, then the Transmit Data Rate Register.

 

So going through your code:

 

-- Line 40 I don't think is necessary - CRU bit 14 is already set to 1 by the soft reset. Should be able to delete this line.

 

-- Line 50 is good - it writes to the Control Register, which also clears CRU bit 14.

 

-- Line 60 is not necessary - CRU bit 12 is already set to 1 by the soft reset.

 

-- Line 70 is interesting - you intended to write to the Receive Data Rate Register, but the highest priority register currently selected (according to the list above) is the Interval Register, so this write goes to that register, which also clears CRU bit 13. (Writing to that register might start the interval timer which generates regular interrupts from the 9902, but I don't think that is a problem in this case.)

 

-- Line 80 is not necessary - CRU bit 11 is already set to 1 by the soft reset.

 

-- Line 90 - you intended to write to the Transmit Data Rate Register, but the highest priority register currently selected (according to the list above) is the Receive Data Rate Register. In the scenario we have at the moment, *both* the Receive and Transmit Data Rate Registers are selected, and in this case this write goes to *both* those registers (programming both with the same Baud rate). This also clears CRU bit 12.

 

-- Line 100 - you're now clearing CRU bits 11 to 14. Bits 14, 13 and 12 are cleared already by writing to the registers, so it shouldn't be necessary to clear those. CRU bit 11 is still set, but the technique normally used to clear this is to write 12 bits in line 90 rather than 11 bits - the extra bit is written to bit 11 which clears it.

 

The new line 55 I suggested to clear CRU bit 13 is deselecting the Interval Register so that the next write doesn't go to it. So your line 70 will write to *both* the Receive and Transmit Data Rate Registers, and your line 90 will write to the Transmit Data Rate Register alone (which is not necessary, but shouldn't cause a problem).

 

Now, I'm not sure exactly why you were having a problem receiving when both the transmit *and* receive registers were being programmed. I may have to experiment a little.

 

I think you should be able to revise your code as below to follow the 'normal' flow for programming the 9902:

 

...

35 CALL IO(3,1,CRU+31,1) !RESET TMS9902

40 (delete line)

50 CALL IO(3,8,CRU,203) !8N1 @ 3MHZ !PROGRAM CONTROL REGISTER

55 CALL IO(3,1,CRU+13,0) !DESELECT INTERVAL REGISTER

60 (delete line)

70 CALL IO(3,12,CRU,0,39) !9600 BPS !PROGRAM RECEIVE AND TRANSMIT DATA RATE REGISTERS

** Note the line above sends 12 bits, not 11 **

80 (delete line)

90 (delete line)

100 (delete line)

110 PRINT "READY FOR INPUT"

...

...

Edited by Stuart
  • Like 2
Link to comment
Share on other sites

Thanks for the explanation Stuart!

I did try out your code suggestion and its works great except that I still had to zero out CRU 11 prior to loading the emit buffer, so I suspect that CRU 11 is not being reset when using a single CALL IO for both the emit and receive rate registers. Also clearing CRU 18 after each reception byte was important otherwise I got overflow errors.

So essentially the issue boiled down to having the interval timer accidentally set and running. Why this would corrupt the reception buffer remains unclear to me...

In any case, I would grab a cigar but it's too darn cold outside still... I'll save it for Spring :grin:

  • Like 2
Link to comment
Share on other sites

Clearing bit 18 after each received byte - yep, got to do that, as per post #13.

 

The CALL IO line to load the transmit and receive rate registers - you modified the line to send 12 bits, not 11, to clear bit 11?

 

(I tried configuring a serial port on my TM990 using assembly, using the configuration you were using, and it actually seemed to work OK. Whether it is the interval timer causing the problem or not, no idea. Glad it's up and running now though.)

  • Like 1
Link to comment
Share on other sites

Clearing bit 18 after each received byte - yep, got to do that, as per post #13.

 

The CALL IO line to load the transmit and receive rate registers - you modified the line to send 12 bits, not 11, to clear bit 11?

 

(I tried configuring a serial port on my TM990 using assembly, using the configuration you were using, and it actually seemed to work OK. Whether it is the interval timer causing the problem or not, no idea. Glad it's up and running now though.)

 

Ah no forgot to send 12 bits...

In any case, thanks yet again for your help! I was really stuck here... I can just imagine how much more difficult it would have been to get timely help back in the day without the internet...

  • Like 2
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...