75XX FPGA DIO
From embeddedTS Manuals
For interacting with the DIO we have developed dioctl. This allows a simple and standard way to control DIO throughout multiple series of our boards. See the dioctl page for more information.
While dioctl will provide the simplest interface, it is not necessarily the fastest method. This example accesses the the FPGA DIO directly.
#include "sbus.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define DIO_Z 2
/*******************************************************************************
* 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;
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)
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));
}
}
/*******************************************************************************
* getdiopin: accepts a DIO pin number and returns its value.
*******************************************************************************/
int getdiopin(int pin)
{
int pinOffSet;
int pinValue = 99999;
/*******************************************************************
*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)
********************************************************************/
if (pin <= 40 && pin >= 37)
{
pinOffSet = pin - 25; // -37 to get to 0, + 10 to correct offset
// Obtain the specific pin value (1 or 0)
pinValue = (sbus_peek16(0x66) >> pinOffSet) & 0x0001;
}
/*********************************************************************
*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; // Easier to understand when LSB = 0 and MSB = 15
// Obtain the specific pin value (1 or 0)
pinValue = (sbus_peek16(0x68) >> pinOffSet) & 0x0001;
}
/*********************************************************************
*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; // Easier to understand when LSB = 0 and MSB = 15
// Obtain the specific pin value (1 or 0)
pinValue = (sbus_peek16(0x6e) >> pinOffSet) & 0x0001;
}
return pinValue;
}
/*******************************************************************************
* Main: accept input from the command line and act accordingly.
*******************************************************************************/
int main(int argc, char **argv)
{
int pin;
int val;
int returnedValue;
// Check for invalid command line arguments
if ((argc > 4) | (argc < 3))
{
printf("Usage: %s <get|set> <pin#> <set_value (0|1|2)>\n", argv[0]);
return 1;
}
// We only want to get val if there are more than 3 command line arguments
if (argc == 3)
pin = strtoul(argv[2], NULL, 0);
else
{
pin = strtoul(argv[2], NULL, 0);
val = strtoul(argv[3], NULL, 0);
}
// If anything other than pins 5 through 40, fail program
assert(pin <= 40 && pin >= 5);
// Parse through the command line arguments, check for valid inputs, and exec
if (!(strcmp(argv[1], "get")) && (argc == 3))
{
sbuslock();
returnedValue = getdiopin(pin);
sbusunlock();
printf("pin#%d = %d \n", pin, returnedValue);
}
else if(!(strcmp(argv[1], "set")) && (argc == 4) && (val <= 2))
{
sbuslock();
setdiopin(pin, val);
sbusunlock();
printf("pin#%d set to %d\n", pin, val);
}
else
{
printf("Usage: %s <get|set> <pin#> <set_value (0|1|2)>\n", argv[0]);
return 1;
}
return 0;
}