I’ve got a couple questions about RLP on my FEZ (Panda II).
First, the documentation states that 10KB of memory is reserved when you enable RLP. Is this 10KB the maximum size of the ELF image that can be loaded? The documentation also states that the only way to reclaim this memory is to “erase the firmware” from the bootloader. Does this mean using the “E” command from bootloader mode, or does it mean that reloading the firmware (using the XMODEM upload procedure) restore the original memory configuration?
Second, I’ve written (included below) a simple “driver” for writing bytes out to a shift register. I’ve done this in the hopes that I can achieve better performance using RLP than I can by “bit-banging” from managed code. What sort of performance improvement am I likely to see? Is this the sort of thing that RLP is appropriate for?
Finally, I’ve included below the code for my shift register bit-banger. I was hoping someone could look over it and tell me if I’ve got the general idea right. It’s the first bit of RLP code I’ve written, and my C is fairly rusty. I’ll be posting this code on code.tinyclr.com when it’s done, if it’s actually useful.
#include "RLP.h"
unsigned int port_clock = 0;
unsigned int port_latch = 0;
unsigned int port_data = 0;
unsigned int port_clear = 0;
// I'm way too ghetto for a real header file...
int Release(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize);
int Initialize(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
port_clock = *(unsigned int*)args[0];
port_latch = *(unsigned int*)args[1];
port_data = *(unsigned int*)args[2];
port_clear = *(unsigned int*)args[3];
// make sure the ports aren't already reserved (latch and clear are optional)
if( RLPext->GPIO.IsReserved(port_clock) == RLP_TRUE )
return -1;
if( RLPext->GPIO.IsReserved(port_data) == RLP_TRUE )
return -2;
if( port_latch > 0 && RLPext->GPIO.IsReserved(port_latch) == RLP_TRUE )
return -3;
if( port_clear > 0 && RLPext->GPIO.IsReserved(port_clear) == RLP_TRUE )
return -4;
// reserve the clock port
if( RLPext->GPIO.ReservePin(port_clock, RLP_TRUE) != RLP_TRUE )
{
Release(0, 0, 0, 0);
return -1;
}
// reserve the data port
if( RLPext->GPIO.ReservePin(port_data, RLP_TRUE) != RLP_TRUE )
{
Release(0, 0, 0, 0);
return -2;
}
// reserve the latch port
if( port_latch > 0 && RLPext->GPIO.ReservePin(port_latch, RLP_TRUE) != RLP_TRUE )
{
Release(0, 0, 0, 0);
return -3;
}
// reserve the clear port
if( port_clear > 0 && RLPext->GPIO.ReservePin(port_clear, RLP_TRUE) != RLP_TRUE )
{
Release(0, 0, 0, 0);
return -4;
}
// enable output mode on the pins, all low initially
RLPext->GPIO.EnableOutputMode(port_clock, RLP_FALSE);
RLPext->GPIO.EnableOutputMode(port_latch, RLP_FALSE);
RLPext->GPIO.EnableOutputMode(port_data, RLP_FALSE);
RLPext->GPIO.EnableOutputMode(port_clear, RLP_FALSE);
// we're done
return 0;
}
int Release(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
if( port_clock != 0 )
{
RLPext->GPIO.ReservePin(port_clock, RLP_FALSE);
port_clock = 0;
}
if( port_latch != 0 )
{
RLPext->GPIO.ReservePin(port_latch, RLP_FALSE);
port_latch = 0;
}
if( port_data != 0 )
{
RLPext->GPIO.ReservePin(port_data, RLP_FALSE);
port_data = 0;
}
if( port_clear != 0 )
{
RLPext->GPIO.ReservePin(port_clear, RLP_FALSE);
port_clear = 0;
}
return 0;
}
int WriteByte(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
unsigned char data = *(unsigned char*)args[0];
unsigned int clear = *(unsigned int*)args[1];
unsigned int lsbf = *(unsigned int*)args[2];
int i = 0;
// clear (if we're clearing, and we have a clear pin)
if( clear == RLP_TRUE && port_clear > 0 )
{
RLPext->GPIO.WritePin(port_clear, RLP_FALSE);
RLPext->GPIO.WritePin(port_clear, RLP_TRUE);
}
// latch false (if we're latching data)
if( port_latch > 0 )
RLPext->GPIO.WritePin(port_latch, RLP_FALSE);
if( lsbf == RLP_TRUE )
{
// write the data, least significant bit first
for( i = 0; i < 8; i++ )
{
// first, bring the clock low
RLPext->GPIO.WritePin(port_clock, RLP_FALSE);
// then, write the data
RLPext->GPIO.WritePin(port_data, data % 2 == 1);
// finally, bring the clock high
RLPext->GPIO.WritePin(port_clock, RLP_TRUE);
// shift right
data = data >> 1;
}
}
else
{
// write the data, most significant bit first
for( i = 0; i < 8; i++ )
{
// first, bring the clock low
RLPext->GPIO.WritePin(port_clock, RLP_FALSE);
// then, write the data
RLPext->GPIO.WritePin(port_data, data >= 128);
// finally, bring the clock high
RLPext->GPIO.WritePin(port_clock, RLP_TRUE);
// shift left
data = data << 1;
}
}
// latch true (if we're latching data)
if( port_latch > 0 )
RLPext->GPIO.WritePin(port_latch, RLP_TRUE);
return 0;
}