this might be a tricky one, I don't even know how to properly enunciate a title for the question...
I am working on a Code Library that is supposed to be multiplatform, ie: Arduino, PSoC Creator, etc. The workaround for enabling the multiplatform support is by means of function pointers that link the hardware with the objects in the processor. This description might be naive so the code below is an example of one library for controlling shift registers.
ShiftRegister.h -> Contains the object related declarations
ShiftRegister.cpp -> Contains the object definitions
ShiftRegister.ino -> Actual Arduino Sketch
ShiftRegister.h
#ifndef SHIFT_REGISTER
#define SHIFT_REGISTER
/////////////////////////////////////////////////////////////////////////////////////
// Link Definitions
#define ENABLE_PIN_ENABLED
#define CLEAR_PIN_ENABLED
#define LENGTH_SCAN_PIN_ENABLED
#define PIN_SETUP_ENABLED
#define DATA_BUFFER_ENABLED
//
/////////////////////////////////////////////////////////////////////////////////////
// Integrated Ciruits Library Include
#include <IC.h>
//
/////////////////////////////////////////////////////////////////////////////////////
// Arduino Specific Code
#define DATA_PIN 8
#define ENABLE_PIN 9
#define LATCH_PIN 10
#define CLOCK_PIN 11
#define CLEAR_PIN 12
#define LENGTH_SCAN 13
/////////////////////////////////////////////////////////////////////////////////////
// Shift Register Object
extern IC::ShiftRegister::Unidirectional::SIPO::Controller SR;
//
/////////////////////////////////////////////////////////////////////////////////////
// Function used to initialize the Shift Register Object
void SR_Start();
//
/////////////////////////////////////////////////////////////////////////////////////
// Functions for linking the Shift Register Object with the hardware
void SR_Data(bool state); // Function Passed to the Shift Register Object
void SR_Clock(bool state); // Function Passed to the Shift Register Object
void SR_Latch(bool state); // Function Passed to the Shift Register Object
#ifdef ENABLE_PIN_ENABLED
void SR_Enable(bool state); // Function Passed to the Shift Register Object
#endif
#ifdef CLEAR_PIN_ENABLED
void SR_Clear(bool state); // Function Passed to the Shift Register Object
#endif
#ifdef LENGTH_SCAN_PIN_ENABLED
bool SR_LengthScan(); // Function Passed to the Shift Register Object
#endif
#ifdef PIN_SETUP_ENABLED
void SR_PinSetup(); // Function Passed to the Shift Register Object
#endif
//
/////////////////////////////////////////////////////////////////////////////////////
#endif//SHIFT_REGISTER
ShiftRegister.cpp
#include "ShiftRegister.h"
// Adjust SR Properties to fit with your circuit
using namespace IC::ShiftRegister::Unidirectional::SIPO;
Controller SR;
///////////////////////////////////////////////////////////////////////////////////////
// Function used to initialize the Shift Register Object
void SR_Start()
{
///////////////////////////////////////////////////////////////////////////////////
// Attach Hardware Link Functions to the Shift Register Object
#ifdef PIN_SETUP_ENABLED
SR.AttachPinSetupAPI(SR_PinSetup);
#else
pinMode(DATA_PIN,OUTPUT);
pinMode(CLOCK_PIN,OUTPUT);
pinMode(LATCH_PIN,OUTPUT);
#ifdef ENABLE_PIN_ENABLED
pinMode(ENABLE_PIN,OUTPUT);
#endif
#ifdef CLEAR_PIN_ENABLED
pinMode(CLEAR_PIN,OUTPUT);
#endif
#ifdef LENGTH_SCAN_PIN_ENABLED
pinMode(LENGTH_SCAN,INPUT);
#endif
#endif
SR.AttachDataAPI(SR_Data);
SR.AttachClockAPI(SR_Clock);
SR.AttachLatchAPI(SR_Latch);
#ifdef ENABLE_PIN_ENABLED
SR.AttachEnableAPI(SR_Enable);
#endif
#ifdef CLEAR_PIN_ENABLED
SR.AttachClearAPI(SR_Clear);
#endif
#ifdef LENGTH_SCAN_PIN_ENABLED
SR.AttachLengthScanAPI(SR_LengthScan);
#else
SR.Properties().SetBitLength(8);
#endif
//
///////////////////////////////////////////////////////////////////////////////////
// Set Shift Register Object Properties for operation
/////////////////////////////////////////////////////////////////////////////////
// Logic Related
SR.SetDataLogic(Data::Logic::Regular);
SR.SetClockLogic(Clock::Logic::Rising);
SR.SetLatchLogic(Latch::Logic::Rising);
#ifdef ENABLE_PIN_ENABLED
SR.SetEnableLogic(Enable::Logic::Mode1);
#endif
#ifdef CLEAR_PIN_ENABLED
SR.SetClearLogic(Clear::Logic::Mode2);
#endif
//
/////////////////////////////////////////////////////////////////////////////////
// Data Management Properties
SR.SetBitNumberingMode(BitNumbering::MsbFirst);
#ifdef DATA_BUFFER_ENABLED
SR.DataBuffer_Enabled();
#endif
//
/////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
SR.Start();
SR.Clear();
#ifdef LENGTH_SCAN_PIN_ENABLED
SR.ScanLength(1);
#endif
}
//
///////////////////////////////////////////////////////////////////////////////////////
// Functions for linking the Shift Register Object with the hardware
/////////////////////////////////////////////////////////////////////////////////////
// Data
void SR_Data(bool state)
{
digitalWrite(DATA_PIN,state);
}
//
/////////////////////////////////////////////////////////////////////////////////////
// Clock
void SR_Clock(bool state)
{
digitalWrite(CLOCK_PIN,state);
}
//
/////////////////////////////////////////////////////////////////////////////////////
// Latch
void SR_Latch(bool state)
{
digitalWrite(LATCH_PIN,state);
}
//
/////////////////////////////////////////////////////////////////////////////////////
// Enable
#ifdef ENABLE_PIN_ENABLED
void SR_Enable(bool state)
{
digitalWrite(ENABLE_PIN,state);
}
#endif
//
/////////////////////////////////////////////////////////////////////////////////////
// Clear
#ifdef CLEAR_PIN_ENABLED
void SR_Clear(bool state)
{
digitalWrite(CLEAR_PIN,state);
}
#endif
//
/////////////////////////////////////////////////////////////////////////////////////
// PinSetup
#ifdef PIN_SETUP_ENABLED
void SR_PinSetup()
{
pinMode(DATA_PIN,OUTPUT);
pinMode(CLOCK_PIN,OUTPUT);
pinMode(LATCH_PIN,OUTPUT);
#ifdef ENABLE_PIN_ENABLED
pinMode(ENABLE_PIN,OUTPUT);
#endif
#ifdef CLEAR_PIN_ENABLED
pinMode(CLEAR_PIN,OUTPUT);
#endif
#ifdef LENGTH_SCAN_PIN_ENABLED
pinMode(LENGTH_SCAN,INPUT);
#endif
}
#endif
//
/////////////////////////////////////////////////////////////////////////////////////
// Length Scan
#ifdef LENGTH_SCAN_PIN_ENABLED
bool SR_LengthScan()
{
return digitalRead(LENGTH_SCAN);
}
#endif
//
/////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////
ShiftRegister.ino
#include "ShiftRegister.h"
void setup()
{
Serial.begin(115200);
//Initialize the SR Object
SR_Start();
}
void loop()
{
SR.SetState(0,1,1);
delay(1000);
SR.SetState(0,0,0);
SR.SetState(1,1,0);
SR.SetState(5,1,1);
delay(1000);
SR.Clear();
delay(1000);
}
Having shown a working example of the structure I am using I want to know if there is a way to implement something that takes care of the functions for linking the Shift Register Object with the hardware, with that I mean that declaring the Hardware functions on arduino would only require setting the hardware pin, example:
Changing ShiftRegister.h to:
#ifndef SHIFT_REGISTER
#define SHIFT_REGISTER
/////////////////////////////////////////////////////////////////////////////////////
// Link Definitions
#define ENABLE_PIN_ENABLED
#define CLEAR_PIN_ENABLED
#define LENGTH_SCAN_PIN_ENABLED
#define PIN_SETUP_ENABLED
#define DATA_BUFFER_ENABLED
//
/////////////////////////////////////////////////////////////////////////////////////
// Integrated Ciruits Library Include
#include <IC.h>
//
/////////////////////////////////////////////////////////////////////////////////////
// Arduino Specific Code
#define DATA_PIN 8
#define ENABLE_PIN 9
#define LATCH_PIN 10
#define CLOCK_PIN 11
#define CLEAR_PIN 12
#define LENGTH_SCAN 13
/////////////////////////////////////////////////////////////////////////////////////
// Shift Register Object
extern IC::ShiftRegister::Unidirectional::SIPO::Controller SR;
//
/////////////////////////////////////////////////////////////////////////////////////
// Function used to initialize the Shift Register Object
void SR_Start();
//
/////////////////////////////////////////////////////////////////////////////////////
#endif//SHIFT_REGISTER
Changing ShiftRegister.cpp to:
#include "ShiftRegister.h"
// Adjust SR Properties to fit with your circuit
using namespace IC::ShiftRegister::Unidirectional::SIPO;
Controller SR;
///////////////////////////////////////////////////////////////////////////////////////
// Function used to initialize the Shift Register Object
void SR_Start()
{
///////////////////////////////////////////////////////////////////////////////////
// Attach Hardware Link Functions to the Shift Register Object
#ifdef PIN_SETUP_ENABLED
SR.AttachPinSetupAPI(ArduinoPinSetupHelper(DATA_PIN,CLOCK_PIN,LATCH_PIN,ENABLE_PIN,CLEAR_PIN,LENGTH_SCAN_PIN));
#else
pinMode(DATA_PIN,OUTPUT);
pinMode(CLOCK_PIN,OUTPUT);
pinMode(LATCH_PIN,OUTPUT);
#ifdef ENABLE_PIN_ENABLED
pinMode(ENABLE_PIN,OUTPUT);
#endif
#ifdef CLEAR_PIN_ENABLED
pinMode(CLEAR_PIN,OUTPUT);
#endif
#ifdef LENGTH_SCAN_PIN_ENABLED
pinMode(LENGTH_SCAN,INPUT);
#endif
#endif
SR.AttachDataAPI(ArduinoDataHelper(DATA_PIN));
SR.AttachClockAPI(ArduinoClockHelper(CLOCK_PIN));
SR.AttachLatchAPI(ArduinoLatchHelper(LATCH_PIN));
#ifdef ENABLE_PIN_ENABLED
SR.AttachEnableAPI(ArduinoEnableHelper(ENABLE_PIN));
#endif
#ifdef CLEAR_PIN_ENABLED
SR.AttachClearAPI(ArduinoClearHelper(CLEAR_PIN));
#endif
#ifdef LENGTH_SCAN_PIN_ENABLED
SR.AttachLengthScanAPI(ArduinoLengthScanHelper(LENGHT_SCAN_PIN));
#else
SR.Properties().SetBitLength(8);
#endif
//
///////////////////////////////////////////////////////////////////////////////////
// Set Shift Register Object Properties for operation
/////////////////////////////////////////////////////////////////////////////////
// Logic Related
SR.SetDataLogic(Data::Logic::Regular);
SR.SetClockLogic(Clock::Logic::Rising);
SR.SetLatchLogic(Latch::Logic::Rising);
#ifdef ENABLE_PIN_ENABLED
SR.SetEnableLogic(Enable::Logic::Mode1);
#endif
#ifdef CLEAR_PIN_ENABLED
SR.SetClearLogic(Clear::Logic::Mode2);
#endif
//
/////////////////////////////////////////////////////////////////////////////////
// Data Management Properties
SR.SetBitNumberingMode(BitNumbering::MsbFirst);
#ifdef DATA_BUFFER_ENABLED
SR.DataBuffer_Enabled();
#endif
//
/////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////
SR.Start();
SR.Clear();
#ifdef LENGTH_SCAN_PIN_ENABLED
SR.ScanLength(1);
#endif
}
//
///////////////////////////////////////////////////////////////////////////////////////
Having this second set of files the only thing missing to implement are the Arduino Helper Funcions that are supposed to take an uint8_t as a parameter and return a function pointer for example to digitalWrite but with the pin parameter preset to a value
Example (I am sure this is plain wrong, but is there only to illustrate what I am trying to achieve)
void(*)(bool) ArduinoDataHelper(uint8_t Pin)
{
return digitalWrite(Pin,state);
}