Finding a workaround for 1-byte packets

The project in my previous thread continues. I’m pretty sure I’m down to one problem before I have full functionality!

That problem is that the code I ported to the Wixel expects a UART to have a buffer storing multiple bytes. The code is written to read 8 byte ‘command packets’ output by the Arbotix Commander to one Wixel, and transmitted via the radio to the other Wixel. However, the Wixel’s wireless communication ‘data packets’ often (always, in my experience) contain a single byte. The radioComRxAvailable() function reports the length of the most recent, aka current data packet. The radioComRxReceiveByte() reads bytes only from the current data packet. In essence, it seems that the data packet is my buffer, and I’m apparently stuck with a 1-byte buffer.

radio_com.c defines #define TX_QUEUE_THRESHOLD 1 by default, which should (based on the comments above this line in the code) result in multi-byte data packets being preferred. Is there some other factor affecting whether multi-byte packets happen? (I’d rather solve this on the Wixel end, than on the Arbotix Commander end)

I’ve attempted to work around this in a simple (and unappealing) approach that is essentially this:

uint8 CmdrReadMsgs(){
	int8 avail = radioComRxAvailable();
	while(avail == TRUE){
		// Code that reads a byte, and exits loop/function when 8 bytes have accumulated...
		avail = radioComRxAvailable();
		while(avail == 0) {	avail = radioComRxAvailable(); }
	}
}

But even that does not seem to let me read multiple bytes within one call to the function… Any insights/ideas on how to get around this? I’ll probably look at the other radio libraries next…

I do know that the correct bytes are being sent from the Commander, as verified by Commander → Wixel UART → other Wixel → other Wixel USB → computer.

The full code for this method is standalone, for purposes of understanding (e.g. what I’m doing with the 8byte ‘command packet’)… :

/* process messages coming from Commander 
 *  format = 0xFF RIGHT_H RIGHT_V LEFT_H LEFT_V BUTTONS EXT checksum_cmdr */
uint8 CmdrReadMsgs(){
	int8 loopCount = 0;
	int8 avail = radioComRxAvailable();
	while(avail == TRUE){
		loopCount += 1;
		if (loopCount > 2)  { ax12LED(61,1);	}

		if(index_cmdr == -1){         // looking for new packet
			if(radioComRxReceiveByte() == 0xff){ //read until packet start
				index_cmdr = 0;
				checksum_cmdr = 0;
			}
		}else if(index_cmdr == 0){
			// add next byte to vals
			vals[index_cmdr] = (unsigned char) radioComRxReceiveByte();
			// look for first real byte (non 0xFF)
			if(vals[index_cmdr] != 0xff){
				checksum_cmdr += (int) vals[index_cmdr];
				index_cmdr++;
			}
		}else{ //for bytes after the 0th byte
			vals[index_cmdr] = (unsigned char) radioComRxReceiveByte(); 
			//loops will sequentially read bytes and store them here
			
			checksum_cmdr += (int) vals[index_cmdr];
			index_cmdr++;
			
			if(index_cmdr == 7){ // packet complete
				if(checksum_cmdr%256 != 255){
					// packet error!
					index_cmdr = -1;
					return 0;
				}
				// DO STUFF
				index_cmdr = -1;
				return 1;
			}
		}
        // delayMicroseconds(250);
        // delayMicroseconds(250);
        // delayMicroseconds(250);
        // delayMicroseconds(249);
		avail = radioComRxAvailable();
		while(avail == 0) {	avail = radioComRxAvailable(); }
	}
	ax12LED(61,0);
	return 0;
}

loopCount and ax12LED() (which toggles a servo’s LED) are my approach to debugging :angry:

Thanks!

Hello.

No, that’s not how it works. If there are between 0 and 1 (TX_QUEUE_THRESHOLD) packets queued to be sent on the radio, then we are not in danger of running out of buffer space yet and the radio_com library will send data is quickly as possible, even if this results in sending some packets that are less than full. If there is more than 1 (TX_QUEUE_THRESHOLD) packet queued to be sent on the radio, then the radio_com library will only queue a new packet to be sent if it has enough data to fill up the packet. So that parameter sets the balance between low latency (sending data as soon as you have it) and high throughput (sending data as soon as you can fill up a radio packet).

If you are just trying to send fixed-size packets over the radio, maybe radio_link and radio_queue would be better libraries to use. The radio_com library is meant to behave more like a UART, dealing with individual bytes. The radio_com library tries to make intelligent guesses about the best way to split the bytes up into radio packets, but the packets are supposed to be an internal implementation detail that the user doesn’t worry about. The radio_com library should be treated like a UART: if it has a byte available for you, then you read the byte into your own buffer and keep track of it from there. Watch for your own buffer to fill up instead of waiting for radioComRxAvailable() to reach 8.

I don’t recommend using the blocking while loops that you posted above because your application is probably neglecting important tasks (like maintaining the USB connection) while those loops are running.

–David

Howdy, thanks for the feedback;

Turns out it was again a user error on my part:
-I’ve gotten too used to thinking of any positive integer being ‘true’. Namely, while(count == True){ } is a bad idea if True is #defined as 1…
-I also had my checksum variable defined as an int8 instead of a uint8, whoops…
-I had neglected to realize that the val array and index_cmdr variable are global. Vals acts as a buffer, and I can get correct results when calling CmdrReadMsgs() multiple times.

I now get through the CmdrReadMsgs() function correctly.

My comments below were typed up last night before discovering my errors earlier today.

Thanks for pointing that out. Missed that nuance.

I agree about taking bytes from packets and creating a local buffer…

That’s why I referred to the code as ‘unappealing’ :). (Not relevant, but, I’m not using USB in this case.)

Thanks again,
-Gert