to turn on and off digital outputs I use the code from sbus.c:
sbuslock();
setdiopin(pin, val);
sbusunlock();
now this is fine and dandy for setting a single pin on or off, but what if I want to set a bank of DIO's
(say pin 31 and 33 ) to both on at the same time.
when I do the setdiopin(31,val);
they don't happen at the same time but rather on after the other.
Now I can see in the code they are bit-mapping, and filtering, but I'm lost in the 1's compliment, and shifting:
pinOffSet = pin - 21;
sbus_poke16(0x6c, sbus_peek16(0x6c) & ~(1 << pinOffSet));
can someone explain what is happening with the above statement? sbus_poke16 looks to me as if it is writing an 8-bit value to the address 0x6c, and its masking to ~(1<<pinOffSet) but I'm getting lost.
/*******************************************************************************
* setdiopin: accepts a DIO register and value to place in that DIO pin.
* Values can be 0 (low), 1 (high), or 2 (z - high impedance).
*******************************************************************************/
void setdiopin(int pin, int val)
{
int pinOffSet;
&nb sp; int dirPinOffSet; // For Register 0x66 only
int outPinOffSet; // For Register 0x66 only
// First, check for the high impedance case
if (val == 2)
{
if (pin <= 40 && pin >= 37)
{
dirPinOffSet = pin - 33;
sbus_poke16(0x66, sbus_peek16(0x66) & ~(1 << dirPinOffSet));
}
else if (pin <= 36 && pin >= 21)
{
pinOffSet = pin - 21;
sbus_poke16(0x6c, sbus_peek16(0x6c) & ~(1 << pinOffSet));
}
else if (pin <= 20 && pin >= 5)
{
pinOffSet = pin - 5;
sbus_poke16(0x72, sbus_peek16(0x72) & ~(1 << pinOffSet));
}
}
/*******************************************************************
*0x66: DIO and tagmem control (RW)
* bit 15-12: DIO input for pins 40(MSB)-37(LSB) (RO)
* bit 11-8: DIO output for pins 40(MSB)-37(LSB) (RW)
* bit 7-4: DIO direction for pins 40(MSB)-37(LSB) (1 - output) (RW)
********************************************************************/
else if (pin <= 40 && pin >= 37)
{
dirPinOffSet = pin - 33; // -37 + 4 = Direction; -37 + 8 = Output
outPinOffSet = pin - 29;
// set bit [pinOffset] to [val] of register [0x66]
if(val)
&n bsp; sbus_poke16(0x66, (sbus_peek16(0x66) | (1 << outPinOffSet)));
else
sbus_poke16(0x66, (sbus_peek16(0x66) & ~(1 << outPinOffSet)));
// Make the specified pin into an output in direction bits
sbus_poke16(0x66, sbus_peek16(0x66) | (1 << dirPinOffSet)); ///
}
/*********************************************************************
*0x68: DIO input for pins 36(MSB)-21(LSB) (RO)
*0x6a: DIO output for pins 36(MSB)-21(LSB) (RW)
*0x6c: DIO direction for pins 36(MSB)-21(LSB) (1 - output) (RW)
*********************************************************************/
else if (pin <= 36 && pin >= 21)
{
pinOffSet = pin - 21;
// set bit [pinOffset] to [val] of register [0x6a]
if(val)
sbus_poke16(0x6a, (sbus_peek16(0x6a) | (1 << pinOffSet)));
else
sbus_poke16(0x6a, (sbus_peek16(0x6a) & ~(1 << pinOffSet)));
// Make the specified pin into an output in direction register
sbus_poke16(0x6c, sbus_peek16(0x6c) | (1 << pinOffSet)); ///
}
/*********************************************************************
*0x6e: DIO input for pins 20(MSB)-5(LSB) (RO)
*0x70: DIO output for pins 20(MSB)-5(LSB) (RW)
*0x72: DIO direction for pins 20(MSB)-5(LSB) (1 - output) (RW)
*********************************************************************/
else if (pin <= 20 && pin >= 5 )
{
pinOffSet = pin - 5;
if(val)
sbus_poke16(0x70, (sbus_peek16(0x70) | (1 << pinOffSet)));
else
sbus_poke16(0x70, (sbus_peek16(0x70) & ~(1 << pinOffSet)));
// Make the specified pin into an output in direction register
sbus_poke16(0x72, sbus_peek16(0x72) | (1 << pinOffSet));
}
}
void sbus_poke16(unsigned int adr, unsigned short dat) {
if (last_gpio_adr != adr >> 5) {
last_gpio_adr = adr >> 5;
cvgpioregs[0] = (cvgpioregs[0] & ~(0x3<<15))|((adr>>5)<<15);
"orr %0, %0, #0x800000\n"
"orr %0, %0, %2, lsl #3\n"
"3: ldr r1, [%3, #0x64]\n"
"2: str %0, [%3, #0x50]\n"
&q uot;1: ldr r1, [%3, #0x64]\n"
: "+r"(dummy) : "r"(adr), "r"(dat), "r"(cvspiregs) : "r1","cc"
unsigned short sbus_peek16(unsigned int adr) {
if (last_gpio_adr != adr >> 5) {
last_gpio_adr = adr >> 5;
cvgpioregs[0] = ((adr>>5)<<15|1<<3|1<<17);
"2: str %0, [%2, #0x50]\n"
"1: ldr r1, [%2, #0x64]\n"
&nb sp; "ldr %0, [%2, #0x58]\n"
"ands r1, %0, #0x10000\n"
"bicne %0, %0, #0xff0000\n"
: "+r"(ret) : "r"(adr), "r"(cvspiregs) : "r1", "cc"