// Raspberry Pi LPC1114 I/O Processor Expansion Board SPI Agent Firmware
// timer 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;
namespace SPIAgent
{
///
/// The Timer class implements LPC1114 32-bit hardware timer services.
///
public class Timer
{
///
/// The LPC1114 system clock frequency is 48 MHz.
///
public const uint PCLK_FREQUENCY = 48000000;
///
/// LPC1114 32-bit timer identifiers.
///
public enum ID
{
CT32B0,
CT32B1,
SENTINEL
}
///
/// LPC1114 32-bit timer modes.
///
public enum MODE
{
DISABLED,
RESET,
PCLK,
CAP0_RISING,
CAP0_FALLING,
CAP0_BOTH,
SENTINEL
}
///
/// LPC1114 32-bit timer capture modes.
///
public enum CAPTURE_EDGE
{
DISABLED,
CAP0_RISING,
CAP0_FALLING,
CAP0_BOTH,
SENTINEL
}
///
/// LPC1114 32-bit timer match registers.
///
public enum MATCH_REGISTER
{
MATCH0,
MATCH1,
MATCH2,
MATCH3,
SENTINEL
}
///
/// LPC1114 32-bit timer match output actions.
///
public enum MATCH_OUTPUT
{
DISABLED,
CLEAR,
SET,
TOGGLE,
SENTINEL
}
///
/// LPC1114 32-bit timer capture and match features.
///
[Flags]
public enum FEATURES
{
INTERRUPT = 0x10,
RESET = 0x20,
STOP = 0x40
}
private ITransport mytransport;
private ID mytimer;
private SPIAGENT_COMMAND_MSG_t cmd;
private SPIAGENT_RESPONSE_MSG_t resp;
///
/// LPC1114 32-bit timer object constructor.
///
/// SPI Agent Firmware transport object.
/// Timer identifier.
/// Timer mode. Default is MODE.DISABLED.
/// Timer prescaler. Default is 1.
public Timer(ITransport spiagent, ID timer, MODE mode = MODE.DISABLED, uint prescaler = 1)
{
// Validate parameters
if (spiagent == null)
{
throw new NullReferenceException("SPI Agent Firmware transport handle is null");
}
if (timer >= ID.SENTINEL)
{
throw new ArgumentException("Timer ID parameter is invalid");
}
if (mode >= MODE.SENTINEL)
{
throw new ArgumentException("Timer mode parameter is invalid");
}
if (prescaler == 0)
{
throw new ArgumentException("Timer prescaler parameter is invalid");
}
cmd = new SPIAGENT_COMMAND_MSG_t();
resp = new SPIAGENT_RESPONSE_MSG_t();
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_INIT_TIMER;
cmd.pin = (int)timer;
cmd.data = 0;
// 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());
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_TIMER_PRESCALER;
cmd.pin = (int)timer;
cmd.data = (int)prescaler;
// 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());
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_TIMER_MODE;
cmd.pin = (int)timer;
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;
mytimer = timer;
}
///
/// Configure LPC1114 hardware timer mode.
///
/// Timer mode
public void ConfigureMode(MODE mode)
{
// Validate parameters
if (mode >= MODE.SENTINEL)
{
throw new ArgumentException("Timer mode parameter is invalid");
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_TIMER_MODE;
cmd.pin = (int)mytimer;
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 LPC1114 32-bit timer prescaler.
///
/// Prescaler value.
public void ConfigurePrescaler(uint prescaler)
{
// Validate parameters
if (prescaler == 0)
{
throw new ArgumentException("Timer prescaler parameter is invalid");
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_TIMER_PRESCALER;
cmd.pin = (int)mytimer;
cmd.data = (int)prescaler;
// 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 LPC1114 32-bit hardware timer capture mode.
///
/// CAP0 input edge.
/// Capture features.
public void ConfigureCapture(CAPTURE_EDGE edge, FEATURES features = 0)
{
// Validate parameters
if (edge >= CAPTURE_EDGE.SENTINEL)
{
throw new ArgumentException("Timer capture edge parameter is invalid");
}
if (((int)features & (~(int)FEATURES.INTERRUPT)) != 0)
{
throw new ArgumentException("Timer capture features parameter is invalid");
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_TIMER_CAPTURE;
cmd.pin = (int)mytimer;
cmd.data = (int)edge | (int)features;
// 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 LPC1114 match register.
///
/// Match register identifier.
/// Match value.
/// Match output action.
/// Match features.
public void ConfigureMatch(MATCH_REGISTER match, uint value, MATCH_OUTPUT action, FEATURES features)
{
// Validate parameters
if (match >= MATCH_REGISTER.SENTINEL)
{
throw new ArgumentException("Timer match register parameter is invalid");
}
if (action >= MATCH_OUTPUT.SENTINEL)
{
throw new ArgumentException("Timer match output action parameter is invalid");
}
if (((int)features & ~((int)FEATURES.INTERRUPT | (int)FEATURES.RESET | (int)FEATURES.STOP)) != 0)
{
throw new ArgumentException("Timer match features parameter is invalid");
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_TIMER_MATCH0 + (int)match;
cmd.pin = (int)mytimer;
cmd.data = (int)action | (int)features;
// 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());
}
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_TIMER_MATCH0_VALUE + (int)match;
cmd.pin = (int)mytimer;
cmd.data = (int)value;
// 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 read-only property returns the LPC1114 32-bit timer counter register.
///
public uint counter
{
get
{
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_GET_TIMER_VALUE;
cmd.pin = (int)mytimer;
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 (uint)resp.data;
}
}
///
/// This read-only property returns the LPC1114 32-bit timer capture register.
///
public uint capture
{
get
{
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_GET_TIMER_CAPTURE;
cmd.pin = (int)mytimer;
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 (uint)resp.data;
}
}
///
/// This read-only property returns the most recent LPC1114 32-bit timer capture delta value.
///
public uint capture_delta
{
get
{
// Build the command message
cmd.command = (int)Commands.SPIAGENT_CMD_GET_TIMER_CAPTURE_DELTA;
cmd.pin = (int)mytimer;
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 (uint)resp.data;
}
}
}
}