// filename stir.c
//
// compile arm-linux-gcc -static-libgcc -o stir stir.c
//

#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>

#define ON  "ON"
#define OFF "OFF"
#define PULSE 5000L   /* Pulse length of 5ms */

static volatile unsigned int *PBDDR;
static volatile unsigned int *PBDR;

void usage()
{
  printf("Usage: stir [ON | OFF]");
}

void print_state()
{
  printf("Current DIO state = %x\n", *PBDR);   
}

void stir_on()
{
  printf("Turn stir motors on...\n");   
  *PBDDR = 0x02;  /* Set direction of DIO 2 to output */
  *PBDR = 0xfd;   /* Set DIO 2 low */

  /* Return output to high after pulse length */
  usleep(PULSE);
  *PBDR = 0xff;
}

void stir_off()
{
  printf("Turn stir motors off...\n");
  *PBDDR = 0x04;  /* Set direction of DIO 3 to output */
  *PBDR = 0xfb;   /* Set DIO 3 low */

  /* Return output to high after pulse length */
  usleep(PULSE);
  *PBDR = 0xff;
}

int main(int argc, char **argv)
{
  unsigned char *start, state;

  int fd = open("/dev/mem", O_RDWR|O_SYNC);

  start = mmap(0,getpagesize(),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0x80840000);
  PBDR = (unsigned int *)(start + 0x04);     // port b data
  PBDDR = (unsigned int *)(start + 0x14);    // port b direction register

  /* No args just reads the DIO, so we're done here */
  if (argc == 1) {
    print_state();
    exit(0);
  }

  printf("Check arguments...\n");
  /* Check arguments. Print help if incorrect. */
  if (argc != 2) {
    usage();
    exit(0);
  }

  if (strcmp(argv[1],ON) && strcmp(argv[1],OFF)) {
    usage();
    exit(0);
  }


  if (!strcmp(argv[1],ON)) {
    stir_on();
    print_state();
  } else if (!strcmp(argv[1], OFF)) {
    stir_off();
    print_state();
  }

  close(fd);
  return 0;
}
