// Raspberry Pi LPC1114 I/O Processor Expansion Board SPI Agent Firmware
// GPIO services
// Copyright (C)2014-2018, Philip Munts, President, Munts AM Corp.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
namespace SPIAgent
{
///
/// The GPIO (General Purpose Input Output) class implements LPC1114 digital input/output services.
///
public class GPIO: IO.Interfaces.GPIO.Pin
{
///
/// LPC1114 GPIO pin data directions.
///
public enum DIRECTION
{
INPUT,
OUTPUT,
SENTINEL
}
///
/// LPC1114 GPIO pin configuration modes.
///
public enum MODE
{
INPUT,
INPUT_PULLDOWN,
INPUT_PULLUP,
OUTPUT,
OUTPUT_OPENDRAIN,
SENTINEL
}
///
/// LPC1114 GPIO pin interrupt modes.
///
public enum INTERRUPT
{
DISABLED,
FALLING,
RISING,
BOTH,
SENTINEL
}
private static HashSet ValidPins = new HashSet();
private ITransport mytransport;
private int mypin;
private SPIAGENT_COMMAND_MSG_t cmd;
private SPIAGENT_RESPONSE_MSG_t resp;
///
/// Static constructor that populates the valid pins table.
///
static GPIO()
{
ValidPins.Add(Pins.LPC1114_INT);
ValidPins.Add(Pins.LPC1114_LED);
ValidPins.Add(Pins.LPC1114_GPIO0);
ValidPins.Add(Pins.LPC1114_GPIO1);
ValidPins.Add(Pins.LPC1114_GPIO2);
ValidPins.Add(Pins.LPC1114_GPIO3);
ValidPins.Add(Pins.LPC1114_GPIO4);
ValidPins.Add(Pins.LPC1114_GPIO5);
ValidPins.Add(Pins.LPC1114_GPIO6);
ValidPins.Add(Pins.LPC1114_GPIO7);
}
///
/// Constructor that configures a GPIO pin, given pin number, data direction, and initial state.
///
/// SPI Agent Firmware transport object.
/// LPC1114 GPIO pin number.
/// LPC1114_GPIO0 through LPC1114_GPIO7 are allowed.
/// LPC1114 GPIO pin data direction.
/// LPC1114 GPIO pin initial state.
/// For an output pin, sets output state to sourcing (1) or sinking (0).
/// For an input pin, sets internal pull-up resistor (1) or pull-down resistor (0).
public GPIO(ITransport spiagent, int pin, DIRECTION dir, bool state)
{
// Validate parameters
if (spiagent == null)
{
throw new NullReferenceException("SPI Agent Firmware transport handle is null");
}
if (!ValidPins.Contains(pin))
{
throw new ArgumentException("GPIO pin number is invalid");
}
if (dir >= DIRECTION.SENTINEL)
{
throw new ArgumentException("GPIO direction parameter is invalid");
}
cmd = new SPIAGENT_COMMAND_MSG_t();
resp = new SPIAGENT_RESPONSE_MSG_t();
// Build the command message
cmd.pin = pin;
switch (dir)
{
case DIRECTION.INPUT:
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_GPIO_INPUT;
cmd.data = state ? 1 : 0;
break;
case DIRECTION.OUTPUT:
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_GPIO_OUTPUT;
cmd.data = state ? 1 : 0;
break;
}
// Dispatch the command
spiagent.Command(cmd, ref resp);
// Handle errors
if (resp.error != 0)
{
throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString());
}
mytransport = spiagent;
mypin = pin;
}
///
/// Constructor that configures a GPIO pin, given pin number and mode.
/// Use this constructor if you need to configure a high-impedance input or an open-drain output.
///
/// SPI Agent Firmware transport object.
/// LPC1114 GPIO pin number.
/// LPC1114_GPIO0 through LPC1114_GPIO7 are allowed.
/// LPC1114 GPIO pin mode.
public GPIO(ITransport spiagent, int pin, MODE mode)
{
// Validate parameters
if (spiagent == null)
{
throw new NullReferenceException("SPI Agent Firmware transport handle is null");
}
if (!ValidPins.Contains(pin))
{
throw new ArgumentException("GPIO pin number is invalid");
}
if (mode >= MODE.SENTINEL)
{
throw new ArgumentException("GPIO mode parameter is invalid");
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_GPIO;
cmd.pin = pin;
cmd.data = (int)mode;
// Dispatch the command
spiagent.Command(cmd, ref resp);
// Handle errors
if (resp.error != 0)
{
throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString());
}
mytransport = spiagent;
mypin = pin;
}
///
/// Configure this GPIO pin's mode.
///
/// LPC1114 GPIO pin mode.
public void ConfigureMode(MODE mode)
{
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_GPIO;
cmd.pin = mypin;
cmd.data = (int)mode;
// Dispatch the command
mytransport.Command(cmd, ref resp);
// Handle errors
if (resp.error != 0)
{
throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString());
}
}
///
/// Configure this GPIO pin's interrupt mode.
/// This only makes sense when running on the Raspberry Pi.
///
/// LPC1114 GPIO pin interrupt mode.
public void ConfigureInterrupt(INTERRUPT intconfig)
{
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_GPIO_INTERRUPT;
cmd.pin = mypin;
cmd.data = (int)intconfig;
// Dispatch the command
mytransport.Command(cmd, ref resp);
// Handle errors
if (resp.error != 0)
{
throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString());
}
}
///
/// This property gets or sets this LPC1114 GPIO pin's state.
///
public bool state
{
get
{
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_GET_GPIO;
cmd.pin = mypin;
cmd.data = 0;
// Dispatch the command
mytransport.Command(cmd, ref resp);
// Handle errors
if (resp.error != 0)
{
throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString());
}
return (resp.data == 1);
}
set
{
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_PUT_GPIO;
cmd.pin = mypin;
cmd.data = value ? 1 : 0;
// Dispatch the command
mytransport.Command(cmd, ref resp);
// Handle errors
if (resp.error != 0)
{
throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString());
}
}
}
}
}