// perform basic initialization of GPIO chip int relayDriverInit (int addr) { int status; onionPrint(ONION_SEVERITY_INFO, "> Initializing Relay Expansion chip\n"); // set all GPIOs to output status = mcp_setAllDirection(addr, 0); if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "relay-exp:init:: Setting output direction failed\n"); return status; } // disable all pullup resistors status = mcp_setAllPullup(addr, 0); if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "relay-exp:init:: Disabling pullup resistors failed\n"); return status; } // set all GPIOs to 0 status = mcp_setAllGpio(addr, 0); if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "relay-exp:init:: Reseting GPIOs failed\n"); return status; } return status; }
int validateArguments(int channel, int state) { int status = EXIT_SUCCESS; if (channel < -1 || channel >= RELAY_EXP_NUM_CHANNELS) { onionPrint(ONION_SEVERITY_FATAL, "ERROR: invalid CHANNEL selection\n"); onionPrint(ONION_SEVERITY_FATAL, "Accepted values are:\n"); onionPrint(ONION_SEVERITY_FATAL, "\t0-1\n"); onionPrint(ONION_SEVERITY_FATAL, "\tall\n"); onionPrint(ONION_SEVERITY_FATAL, "\n"); status = EXIT_FAILURE; } if (state != 0 && state != 1) { onionPrint(ONION_SEVERITY_FATAL, "ERROR: invalid STATE selection\n"); onionPrint(ONION_SEVERITY_FATAL, "Accepted values are:\n"); onionPrint(ONION_SEVERITY_FATAL, "\t0 or 1\n"); onionPrint(ONION_SEVERITY_FATAL, "\n"); status = EXIT_FAILURE; } return status; }
// set GPIO value - change the relay state int relaySetChannel (int addr, int channel, int state) { int status; // set the relay channel to the specified state onionPrint(ONION_SEVERITY_INFO, "> Setting RELAY%d to %s\n", channel, ( state == 1 ? "ON" : "OFF") ); status = mcp_setGpio(addr, channel, state); return status; }
// read GPIO calue, ie read the relay state int relayReadState (int addr, int channel, int* state) { int status; // read the relay state status = mcp_getGpio(addr, channel, state); onionPrint(ONION_SEVERITY_INFO, "> Reading RELAY%d state: %s\n", channel, ( *state == 1 ? "ON" : "OFF") ); return status; }
// set value to both GPIO0 and GPIO1 (both relay states) int relaySetAllChannels (int addr, int state) { int status, val; onionPrint(ONION_SEVERITY_INFO, "> Setting both RELAYS to %s\n", ( state == 1 ? "ON" : "OFF") ); // translate state to register value if (state == 0) { val = 0x0; } else { val = 0x3; // enable GPIO0 and GPIO1 } // set the all relay channels to the specified state status = mcp_setAllGpio(addr, val); return status; }
void usage(const char* progName) { onionPrint(ONION_SEVERITY_FATAL, "\n"); onionPrint(ONION_SEVERITY_FATAL, "Usage: relay-exp -i\n"); onionPrint(ONION_SEVERITY_FATAL, "\n"); onionPrint(ONION_SEVERITY_FATAL, "FUNCTIONALITY:\n"); onionPrint(ONION_SEVERITY_FATAL, "\tJust initialize the Relay chip\n"); onionPrint(ONION_SEVERITY_FATAL, "\n\n"); onionPrint(ONION_SEVERITY_FATAL, "Usage: relay-exp [-qvi] [-s <bbb>] CHANNEL STATE\n"); onionPrint(ONION_SEVERITY_FATAL, "\n"); onionPrint(ONION_SEVERITY_FATAL, "CHANNEL is the specified Relay channel on the Expansion\n"); onionPrint(ONION_SEVERITY_FATAL, "\tcan be: 0-1 to control a single channel\n"); onionPrint(ONION_SEVERITY_FATAL, "\tcan be: 'all' to control all channels simultaneously\n"); onionPrint(ONION_SEVERITY_FATAL, "STATE is the desired operational state of the relay\n"); onionPrint(ONION_SEVERITY_FATAL, "\tcan be: 0 relay switch is OFF\n"); onionPrint(ONION_SEVERITY_FATAL, "\tcan be: 1 relay switch is ON\n"); onionPrint(ONION_SEVERITY_FATAL, "\n"); onionPrint(ONION_SEVERITY_FATAL, "FUNCTIONALITY:\n"); onionPrint(ONION_SEVERITY_FATAL, "\tProgram the CHANNEL to the specified relay state\n"); onionPrint(ONION_SEVERITY_FATAL, "\n"); onionPrint(ONION_SEVERITY_FATAL, "OPTIONS:\n"); onionPrint(ONION_SEVERITY_FATAL, " -q quiet: no output\n"); onionPrint(ONION_SEVERITY_FATAL, " -v verbose: lots of output\n"); onionPrint(ONION_SEVERITY_FATAL, " -h help: show this prompt\n"); onionPrint(ONION_SEVERITY_FATAL, " -i initialize the relay chip\n"); onionPrint(ONION_SEVERITY_FATAL, " -s <bbb> dip-switch configuration in binary, not required if 000\n"); onionPrint(ONION_SEVERITY_FATAL, "\n"); }
int main(int argc, char** argv) { const char *progname; char *switchAddr; int status; int verbose; int init; int ch; int channel; int relayState; int devAddr; int bInitialized; // set defaults init = 0; verbose = ONION_VERBOSITY_NORMAL; switchAddr = malloc(RELAY_EXP_ADDR_SWITCH_NUM * sizeof *switchAddr); strcpy(switchAddr, RELAY_EXP_ADDR_SWITCH_DEFAULT_VAL); // save the program name progname = argv[0]; //// parse the option arguments while ((ch = getopt(argc, argv, "vqhis:")) != -1) { switch (ch) { case 'v': // verbose output verbose++; break; case 'q': // quiet output verbose = ONION_VERBOSITY_NONE; break; case 'i': // perform init sequence init = 1; break; case 's': // capture binary strcpy (switchAddr, optarg); break; default: usage(progname); return 0; } } // set the verbosity onionSetVerbosity(verbose); // advance past the option arguments argc -= optind; argv += optind; // process the switch address status = processSwitchAddr(switchAddr, &devAddr); if (status == EXIT_FAILURE) { usage(progname); onionPrint(ONION_SEVERITY_FATAL, "ERROR: invalid switch address argument!\n"); return 0; } if (strcmp(switchAddr, RELAY_EXP_ADDR_SWITCH_DEFAULT_VAL) != 0) { onionPrint(ONION_SEVERITY_INFO, "> Switch configuration: %s\n", switchAddr); } // check if just initialization if ( argc == 0 && init == 1 ) { status = relayDriverInit(devAddr); if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "main-relay-exp:: relay init failed!\n"); } return 0; } // ensure correct number of arguments if ( argc != 2) { usage(progname); onionPrint(ONION_SEVERITY_FATAL, "ERROR: invalid amount of arguments!\n"); return 0; } //// parse the arguments // first arg - channel channel = readChannelArgument(argv[0]); // second arg - relay state (on or off) if ( strcmp(argv[1], "off") == 0 || strcmp(argv[1], "Off") == 0 || strcmp(argv[1], "OFF") == 0 ) { relayState = 0; } else if ( strcmp(argv[1], "on") == 0 || strcmp(argv[1], "On") == 0 || strcmp(argv[1], "ON") == 0 ) { relayState = 1; } else { relayState = (int)strtol(argv[1], NULL, 10); } // validate the arguments status = validateArguments(channel, relayState); if (status == EXIT_FAILURE) { return 0; } //// RELAY PROGRAMMING // check if initialized status = relayCheckInit(devAddr, &bInitialized); // exit the app if i2c reads fail if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "> ERROR: Relay Expansion not found!\n"); return 0; } // perform initialization if (init == 1 || bInitialized == 0) { status = relayDriverInit(devAddr); if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "main-relay-exp:: relay init failed!\n"); } } // set the relay state if (channel < 0) { // program both relays at once status = relaySetAllChannels(devAddr, relayState); if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "main-relay-exp:: all relay setup failed!\n"); } } else { // program just one relay status = relaySetChannel(devAddr, channel, relayState); if (status == EXIT_FAILURE) { onionPrint(ONION_SEVERITY_FATAL, "main-relay-exp:: relay %d setup failed!\n", channel); } } return 0; }