//XBeeReset.cpp

// Program to drive arduino gpio pin 7 connected to XBee module reset pin5
// low for 1 second.  Put gpio pin 7 in input mode before and after to avoid 
// driving the pin high when XBee pin 5 may be used as an open collector output.
// M.Holler 1/13/14 

#include <fcntl.h> // These 4 includes are standard Linux headers
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "gpio_test.h" // contains pcDuino specific paths from Sparkfun

// These arrays will become file descriptors for the 18 IO pin and mode files.
int pinMode[1];
int pinData[1];
// Life is easier if we make a constant for our port name.
static const char* portName = "/dev/ttyS1";

int main(void)
{
  int i = 7;      // pin 7 is the pin we are using to reset the XBee 
  char inputBuffer = HIGH; // create and clear a buffer for data from pins
  char path[256]; // nice, long buffer to hold the path name for pin access

  //   - initialize the file descriptor(handle) for the pin mode file
  //   - initialize the file descriptor(handle)for the pin data file
  //   - make pcDuino pin 7 output
  //   - set pin low
  //   - set pin back high
  //   - set pin to input mode to disable output drive. 
  //   - the XBee reset pin has a 20K internal pullup on it to keep it high.

    // Clear the path variable...
    memset(path,0,sizeof(path));
    // ...then assemble the path variable for the current pin mode file...
    sprintf(path, "%s%s%d", GPIO_MODE_PATH, GPIO_FILENAME, i);
    // ...and create a file descriptor...
    pinMode[i] = open(path, O_RDWR);
    // ...then rinse, repeat, for the pin data files.
    memset(path,0,sizeof(path));
    sprintf(path, "%s%s%d", GPIO_PIN_PATH, GPIO_FILENAME, i);
    pinData[i] = open(path, O_RDWR); 

    // Now that we have descriptors, make the pin an output, then set it low.
    setPinMode(pinMode[i], OUTPUT);
    setPin(pinData[i], LOW);
    printf("pcDuino GPIO %d set low\n", i);  // Print info to the command line.
    usleep(250000); // 0.5 sec delay
    setPin(pinData[i], HIGH);
    printf("pcDuino GPIO %d HIGH\n", i);
    setPinMode(pinMode[i], INPUT);
    printf("PcDuino GPIO %d set to Input mode \n", i);

} // end main()

// These two 'set' functions are just wrappers to the writeFile() function to
//   make the code prettier.  Bullshit, it adds an unnecessary layer of obfuscation 
//   which hides an ugly hack two calls down. 
void setPinMode(int pinID, int mode)
{
  writeFile(pinID, mode);
}

void setPin(int pinID, int state)
{
  writeFile(pinID, state);
}

// While it seems okay to only *read* the first value from the file, you
//   seemingly must write four bytes to the file to get the I/O setting to
//   work properly. This function does that. Otherwise known as a hack.
void writeFile(int fileID, int value)
{
  char buffer[4];  // A place to build our four-byte string.
  memset((void *)buffer, 0, sizeof(buffer)); // clear the buffer out.
  sprintf(buffer, "%c", value);
  lseek(fileID, 0, SEEK_SET);   // Make sure we're at the top of the file!
  write(fileID, buffer, sizeof(buffer));
}


