--- /dev/null
+/****************************************************************/\r
+/**@file PCT7303B.c:\r
+ * Description: API layer for TEDIA PCT-7303B card. *\r
+ * Dependency: Windows 32, Windows 64 or Linux *\r
+ * Copyright 2010 Jaroslav Fojtik *\r
+ ****************************************************************/\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+#include <windows.h>\r
+#else\r
+#include <sys/io.h>\r
+#endif\r
+#include <malloc.h>\r
+#include <math.h>\r
+\r
+#include "hudaqlib.h"\r
+#include "hudaq_internal.h"\r
+\r
+\r
+#define DI_CHANNELS 1 ///< Amount of Digital Outputs\r
+#define DO_CHANNELS 1 ///< Amount of Digital Inputs\r
+#define DA_CHANNELS 0 ///< Amount of Analog Outputs\r
+#define AD_CHANNELS 0 ///< Amount of Analog Inputs\r
+#define ENC_CHANNELS 3 ///< Amount of Encoders\r
+#define CTR_CHANNELS 1 ///< Amount of counters\r
+#define STEP_CHANNELS 0 ///< Amount of steppers\r
+\r
+\r
+#define MASTERFREQUENCY 1000 ///< Internal oscillator frequency is 1kHz\r
+\r
+#define IrcResetCounter 2 ///< Binary flag for IrcOptions\r
+\r
+\r
+/** Cache of PCT-7303B state */\r
+typedef struct\r
+{\r
+ UserDataHeader Hdr; ///< General device setup\r
+\r
+ int EncOptions[ENC_CHANNELS]; ///< Bit options for encoders\r
+\r
+ unsigned __int8 DOReg; ///< Port configuration register\r
+ unsigned __int8 IRQCfgReg;\r
+ unsigned __int8 INTEnReg;\r
+ unsigned __int8 TimerReg;\r
+ unsigned __int8 CNTEnReg;\r
+} PCT_7303B_Private;\r
+\r
+\r
+/** Symbolic aliases for available registers inside BADR1 read. */\r
+typedef enum\r
+{\r
+ DINReg = 0, // RD only\r
+ DOUTReg = 4, // WR only\r
+\r
+ IRQCfgReg = 0x180, // WR only\r
+ IRQStatusReg = 0x180, // RD only\r
+ IRQClrReg = 0x184, // WR only\r
+\r
+ TimerReg = 0x3F0, // RW\r
+ INTEnReg = 0x18C, // WR only\r
+\r
+ CNT0SetReg = 0x200, // RW\r
+ CNT1SetReg = 0x204, // RW\r
+ CNT2SetReg = 0x208, // RW\r
+\r
+ CNTEnReg = 0x380, // WR only\r
+ CNTCtrReg= 0x384, // WR only\r
+\r
+} MEM_BAR1; // Memory space #0 on F1\r
+\r
+\r
+/** write to memory mapped device byte wise, bytes are stored on every 4th position. */\r
+static __inline void StoreByte(size_t Ptr, int Offset, unsigned __int8 value)\r
+{\r
+ ((volatile unsigned __int8 *)(Ptr))[Offset] = value;\r
+}\r
+\r
+static __inline void StoreDword(size_t Ptr, int Offset, unsigned __int32 value)\r
+{\r
+ ((volatile unsigned __int32 *)(Ptr))[Offset] = value;\r
+}\r
+\r
+\r
+/** write to memory mapped device byte wise through cache. */\r
+static __inline void StoreCachedByte(size_t Ptr, int Offset, unsigned __int8 value, unsigned __int8 *CachedValue)\r
+{\r
+ if (*CachedValue != value)\r
+ {\r
+ *CachedValue = value;\r
+ StoreByte(Ptr,Offset,value);\r
+ }\r
+}\r
+\r
+\r
+/** This inline is used for reading tightly packed OX9162 local configuration registers. */\r
+static __inline unsigned __int8 GetBytePlain(size_t Ptr, int Offset)\r
+{\r
+ return ((volatile unsigned __int8 *)(Ptr))[Offset];\r
+}\r
+\r
+\r
+/****************************************************************\r
+ * *\r
+ * DIGITAL INPUTS & OUTPUTS *\r
+ * *\r
+ ****************************************************************/\r
+\r
+\r
+/** Get data from digital input. */\r
+static int PCT7303DIRead(const DeviceRecord *DevRecord, unsigned channel)\r
+{\r
+ if (channel>=DI_CHANNELS) return HUDAQBADARG;\r
+ return GetBytePlain(DevRecord->DrvRes.Resources.MemResources[0].Base,DINReg);\r
+}\r
+\r
+\r
+/** Write data to digital output. */\r
+static HUDAQSTATUS PCT7303DOWrite(const DeviceRecord *DevRecord, unsigned channel, unsigned value)\r
+{\r
+ if (channel>=DO_CHANNELS) return HUDAQBADARG;\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, DOUTReg, value,\r
+ &((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->DOReg);\r
+ return HUDAQSUCCESS;\r
+}\r
+\r
+\r
+/** Write one bit to digital output. */\r
+static void PCT7303DOWriteBit(const DeviceRecord *DevRecord, unsigned channel, unsigned bit, int value)\r
+{\r
+ __int8 DoutByte;\r
+\r
+ if (channel>=DO_CHANNELS) return;\r
+ if (bit>=8) return; //there are only 8 bits available in PCT7303\r
+\r
+ DoutByte = (((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->DOReg);\r
+ if (value) DoutByte |= (1<<bit);\r
+ else DoutByte &= ~(1<<bit);\r
+\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, DOUTReg, DoutByte,\r
+ & ((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->DOReg);\r
+}\r
+\r
+\r
+static void PCT7303DOWriteMultipleBits(const DeviceRecord *DevRecord, unsigned channel, unsigned mask, unsigned value)\r
+{\r
+ __int8 DoutByte;\r
+\r
+ if (channel>=DO_CHANNELS) return;\r
+\r
+ DoutByte = (((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->DOReg);\r
+ DoutByte = (DoutByte & ~mask) | (value & mask);\r
+\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, DOUTReg, DoutByte,\r
+ &((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->DOReg);\r
+}\r
+\r
+\r
+static double PCT7303DIOGetParameter(unsigned channel, HudaqParameter param)\r
+{\r
+ switch((int)param)\r
+ {\r
+ case HudaqDINUMBITS:\r
+ return (channel<DI_CHANNELS) ? 8 : WRONG_VALUE;\r
+ case HudaqDONUMBITS:\r
+ return (channel<DO_CHANNELS) ? 8 : WRONG_VALUE;\r
+ case HudaqDINUMCHANNELS:\r
+ return DI_CHANNELS;\r
+ case HudaqDONUMCHANNELS:\r
+ return DO_CHANNELS;\r
+ }\r
+\r
+ return WRONG_VALUE;\r
+}\r
+\r
+\r
+static HUDAQSTATUS PCT7303DIOSetParameter(const DeviceRecord *DevRecord, unsigned channel, HudaqParameter param, int value)\r
+{\r
+\r
+ switch((int)param)\r
+ {\r
+ case HudaqDINUMBITS:\r
+ if(channel>=DI_CHANNELS) return WRONG_VALUE;\r
+ return (value==8) ? 0 : WRONG_VALUE;\r
+ case HudaqDONUMBITS:\r
+ if(channel>=DI_CHANNELS) return WRONG_VALUE;\r
+ return (value==8) ? 0 : WRONG_VALUE;\r
+ case HudaqDINUMCHANNELS:\r
+ return DI_CHANNELS;\r
+ case HudaqDONUMCHANNELS:\r
+ return DO_CHANNELS;\r
+ case HudaqDOMODE:\r
+ if(channel>=DO_CHANNELS) return WRONG_VALUE;\r
+ return HUDAQSUCCESS;\r
+ }\r
+\r
+ return WRONG_VALUE;\r
+}\r
+\r
+\r
+/****************************************************************\r
+ * *\r
+ * ENCODERS *\r
+ * *\r
+ ****************************************************************/\r
+\r
+static double PCT7303BEncGetParameter(const DeviceRecord *DevRecord, unsigned channel, HudaqParameter param)\r
+{\r
+ //size_t Ptr1;\r
+ PCT_7303B_Private *Cache;\r
+\r
+ Cache = (PCT_7303B_Private *)DevRecord->DrvRes.DriverData;\r
+ if (channel>=ENC_CHANNELS) return WRONG_VALUE;\r
+\r
+ switch(param)\r
+ {\r
+ case HudaqEncRESETONREAD:\r
+ return(Cache->EncOptions[channel] & IrcResetCounter);\r
+\r
+ /*\r
+ case HudaqEncMODE:\r
+ pCTRi = (IRC_Control *)&(((char *)&(Cache->EncCache))[channel]);\r
+ return(pCTRi->IRC_MODE);\r
+ case HudaqEncCOUNTCONTROL:\r
+ pCTRi = (IRC_Control *)&(((char *)&(Cache->EncCache))[channel]);\r
+ return(pCTRi->BLOCK_MODE);\r
+ case HudaqEncRESETMODE:\r
+ pCTRi = (IRC_Control *)&(((char *)&(Cache->EncCache))[channel]);\r
+ return(pCTRi->RESET_MODE);\r
+ case HudaqEncI:\r
+ *(__int32 *)IrcValue = GetDword(DevRecord->DrvRes.Resources.MemResources[0].Base, IRCSTATUS);\r
+ return(IrcValue[channel]);\r
+ */\r
+ case HudaqEncNUMCHANNELS:\r
+ return ENC_CHANNELS;\r
+ }\r
+\r
+ return WRONG_VALUE;\r
+}\r
+\r
+\r
+static HUDAQSTATUS PCT7303BEncSetParameter(const DeviceRecord *DevRecord, unsigned channel, HudaqParameter param, double value)\r
+{\r
+ size_t Ptr1;\r
+ PCT_7303B_Private *Cache;\r
+\r
+ Cache = (PCT_7303B_Private *)DevRecord->DrvRes.DriverData;\r
+ if (channel>=ENC_CHANNELS) return HUDAQBADARG;\r
+ Ptr1 = DevRecord->DrvRes.Resources.MemResources[0].Base;\r
+\r
+ switch(param)\r
+ {\r
+ case HudaqEncRESETONREAD:\r
+ if(value!=0)\r
+ Cache->EncOptions[channel] |= IrcResetCounter;\r
+ else\r
+ Cache->EncOptions[channel] &= ~IrcResetCounter;\r
+ return HUDAQSUCCESS;\r
+\r
+ /*\r
+ case HudaqEncMODE:\r
+ if (value<0 || value>=4) return HUDAQBADARG;\r
+ *(unsigned __int32 *)&IrcValue = Cache->EncCache;\r
+ pCTRi = (IRC_Control *)&IrcValue[channel];\r
+\r
+ pCTRi->IRC_MODE = (int)value;\r
+ StoreCachedDword(Ptr2, IRCCTRL, *(unsigned __int32 *)&IrcValue, &Cache->EncCache);\r
+ return HUDAQSUCCESS;\r
+\r
+ case HudaqEncRESETMODE:\r
+ if (value<0 || value>=7) return HUDAQBADARG;\r
+ *(unsigned __int32 *)&IrcValue = Cache->EncCache;\r
+ pCTRi = (IRC_Control *)&IrcValue[channel];\r
+\r
+ pCTRi->RESET_MODE = (int)value;\r
+ StoreCachedDword(Ptr2, IRCCTRL, *(unsigned __int32 *)&IrcValue, &Cache->EncCache);\r
+ return HUDAQSUCCESS;\r
+\r
+ case HudaqEncCOUNTCONTROL:\r
+ if (value<0 || value>=4) return HUDAQBADARG;\r
+ *(unsigned __int32 *)&IrcValue = Cache->EncCache;\r
+ pCTRi = (IRC_Control *)&IrcValue[channel];\r
+\r
+ pCTRi->BLOCK_MODE = (int)value;\r
+ StoreCachedDword(Ptr2, IRCCTRL, *(unsigned __int32 *)&IrcValue, &Cache->EncCache);\r
+ return HUDAQSUCCESS;\r
+ */\r
+ }\r
+\r
+ return HUDAQNOTSUPPORTED;\r
+}\r
+\r
+\r
+/* static HUDAQSTATUS PCT7303BEncReset(const DeviceRecord *DevRecord, unsigned channel)\r
+ {\r
+ size_t Ptr2;\r
+ MF624_Private *Cache;\r
+ __int8 IrcValue[ENC_CHANNELS];\r
+ IRC_Control *pCTRi;\r
+ char OldResetMode;\r
+\r
+ Cache = (MF624_Private *)DevRecord->DrvRes.DriverData;\r
+ if (channel>=ENC_CHANNELS) return HUDAQBADARG;\r
+ Ptr2 = DevRecord->DrvRes.Resources.MemResources[0].Base;\r
+\r
+ *(unsigned __int32*)&IrcValue = Cache->EncCache;\r
+ pCTRi = (IRC_Control *)&IrcValue[channel];\r
+\r
+ OldResetMode = pCTRi->RESET_MODE; //store original reset mode\r
+ pCTRi->RESET_MODE = 1; //reset encoder\r
+ StoreDword(Ptr2, IRCCTRL, *(unsigned __int32 *)&IrcValue);\r
+ pCTRi->RESET_MODE = OldResetMode; //enable counting\r
+ StoreDword(Ptr2, IRCCTRL, *(unsigned __int32 *)&IrcValue);\r
+ return HUDAQSUCCESS;\r
+ } */\r
+\r
+\r
+static int PCT7303BEncRead(const DeviceRecord *DevRecord, unsigned channel)\r
+{\r
+ size_t Ptr1;\r
+ __int32 RetVal;\r
+ PCT_7303B_Private *Cache;\r
+\r
+ if (channel>=ENC_CHANNELS) return 0;\r
+ Cache = (PCT_7303B_Private *)DevRecord->DrvRes.DriverData;\r
+ Ptr1 = DevRecord->DrvRes.Resources.MemResources[0].Base;\r
+\r
+ // read a value from encoder\r
+ StoreByte(Ptr1, CNTCtrReg, 1<<channel); \r
+ RetVal = GetBytePlain(Ptr1,CNT0SetReg) + \r
+ 0x100 * GetBytePlain(Ptr1,CNT1SetReg) +\r
+ 0x10000 * GetBytePlain(Ptr1,CNT2SetReg);\r
+\r
+ if(Cache->EncOptions[channel] & IrcResetCounter) //RESET counter on every read\r
+ {\r
+ StoreByte(Ptr1, CNT0SetReg, 0);\r
+ StoreByte(Ptr1, CNT1SetReg, 0);\r
+ StoreByte(Ptr1, CNT2SetReg, 0);\r
+ StoreByte(Ptr1, CNTCtrReg, 0x10<<channel);\r
+ }\r
+\r
+ return RetVal;\r
+}\r
+\r
+\r
+/****************************************************************\r
+ * *\r
+ * COUNTERS PWM + Count + Step *\r
+ * *\r
+ ****************************************************************/\r
+\r
+static HUDAQSTATUS PCT7303BPWMWrite(const DeviceRecord *DevRecord, unsigned channel, double frequency, double dutycycle)\r
+{\r
+ double T;\r
+\r
+ if (channel>=CTR_CHANNELS) return HUDAQBADARG;\r
+\r
+ if (frequency<=0) return HUDAQBADARG; //Allow duty cycle 0 and 1 for f=0.\r
+\r
+ T = MASTERFREQUENCY/frequency;\r
+ if(T<1) \r
+ {\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, TimerReg, 1,\r
+ & ((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->TimerReg);\r
+ return HUDAQPARTIAL;\r
+ }\r
+ if(T>255)\r
+ {\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, TimerReg, 255,\r
+ & ((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->TimerReg);\r
+ return HUDAQPARTIAL;\r
+ }\r
+\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, TimerReg, \r
+ (unsigned __int8)T,\r
+ &((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->TimerReg);\r
+\r
+ return HUDAQSUCCESS;\r
+}\r
+\r
+\r
+static HUDAQSTATUS PCT7303BCtrReset(const DeviceRecord *DevRecord, unsigned channel)\r
+{\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, TimerReg,\r
+ 0, &((PCT_7303B_Private *)(DevRecord->DrvRes.DriverData))->TimerReg);\r
+ return HUDAQSUCCESS;\r
+}\r
+\r
+\r
+static int PCT7303BCtrRead(const DeviceRecord *DevRecord, unsigned channel)\r
+{\r
+ if (channel>=CTR_CHANNELS) return 0;\r
+ return GetBytePlain(DevRecord->DrvRes.Resources.MemResources[0].Base, TimerReg);\r
+ return 0;\r
+}\r
+\r
+\r
+/********************************************************************/\r
+\r
+/* Initialization procedure for PCT-7303B card. */\r
+static int InitPCT7303(DeviceRecord *DevRecord, int IniOptions)\r
+{\r
+ PCT_7303B_Private *Cache;\r
+ size_t Base;\r
+\r
+ if (DevRecord==NULL) return -1;\r
+\r
+ if (DevRecord->DrvRes.Resources.NumMemResources<2) return -2; //insufficient amount of resources\r
+ Cache = DevRecord->DrvRes.DriverData;\r
+ if (Cache==NULL) return -3;\r
+ if (DevRecord->DrvRes.DriverDataSize<sizeof(PCT_7303B_Private)) return -4;\r
+\r
+ DevRecord->pCT = &CTPCT7303;\r
+\r
+ if ((IniOptions & HudaqOpenNOINIT)==0)\r
+ { //initialize hardware only if no other application is running\r
+ Base = DevRecord->DrvRes.Resources.MemResources[0].Base;\r
+\r
+ /* Disable interrupts */\r
+ Cache->IRQCfgReg = 0;\r
+ StoreByte(Base, IRQCfgReg, 0);\r
+ Cache->INTEnReg = 0; /* Clear interrupt logic. */\r
+ StoreByte(Base, INTEnReg, 0);\r
+\r
+ /* Initialization of DI and DO. */\r
+ Cache->DOReg = 0;\r
+ StoreByte(Base, DOUTReg, 0);\r
+\r
+ /* Initialization of internal timer/counter. */\r
+ Cache->TimerReg = 0;\r
+ StoreByte(Base, TimerReg, 0); /* Stop timer. */\r
+\r
+ /* Initialization of encoders. */\r
+ Cache->CNTEnReg = 0;\r
+ StoreByte(Base, CNTEnReg, 0); /* Stop encoders. */\r
+ }\r
+\r
+ return 1; //success\r
+}\r
+\r
+\r
+/** Internal cleanup procedure for PCT7303B */\r
+static void DonePCT7303(DeviceRecord *DevRecord)\r
+{\r
+ if (DevRecord==NULL) return;\r
+\r
+ DevRecord->pCT = &CtDummy;\r
+}\r
+\r
+\r
+\r
+/****************************************************************\r
+ * *\r
+ * GET/SET PARAMETERS *\r
+ * *\r
+ ****************************************************************/\r
+\r
+\r
+static HUDAQSTATUS PCT7303IRQSetParameter(const DeviceRecord *DevRecord, unsigned channel, HudaqParameter param, int value)\r
+{\r
+ size_t Base;\r
+\r
+ Base = DevRecord->DrvRes.Resources.MemResources[0].Base;\r
+\r
+ /*\r
+ switch((int)param)\r
+ {\r
+ case HudaqIRQ+0:\r
+ {\r
+ if(value)\r
+ {\r
+ StoreCachedByte(Base, IRQCfgReg, 1, &((PCT_7303B_Private *)DevRecord->DrvRes.DriverData)->IRQCfgReg);\r
+ StoreByte(Base, IRQClrReg, 0xFF);\r
+ StoreCachedByte(Base, INTEnReg, 0x80, &((PCT_7303B_Private *)DevRecord->DrvRes.DriverData)->INTEnReg);\r
+ }\r
+ else\r
+ { \r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, INTEnReg, 0,\r
+ &((PCT_7303B_Private *)DevRecord->DrvRes.DriverData)->INTEnReg);\r
+ StoreCachedByte(DevRecord->DrvRes.Resources.MemResources[0].Base, IRQCfgReg, 0,\r
+ &((PCT_7303B_Private *)DevRecord->DrvRes.DriverData)->IRQCfgReg);\r
+ }\r
+ return HUDAQSUCCESS;\r
+ }\r
+ case HudaqIRQ+1:\r
+ return HUDAQSUCCESS;\r
+ }\r
+ */\r
+\r
+ return WRONG_VALUE;\r
+}\r
+\r
+\r
+static double PCT7303IRQGetParameter(const DeviceRecord *DevRecord, unsigned channel, HudaqParameter param)\r
+{\r
+ switch((int)param)\r
+ {\r
+ case HudaqIRQ+0: \r
+ return ((PCT_7303B_Private *)DevRecord->DrvRes.DriverData)->Hdr.IRQcounter;\r
+ }\r
+ return WRONG_VALUE;\r
+}\r
+\r
+\r
+static HUDAQSTATUS PCT7303SetParameter(const DeviceRecord *DevRecord, unsigned channel, HudaqParameter param, double value)\r
+{\r
+ switch(param & HudaqSubsystemMASK)\r
+ {\r
+ case HudaqDI:\r
+ case HudaqDO: return PCT7303DIOSetParameter(DevRecord,channel,param,(int)value);\r
+ // case HudaqAI: \r
+ // case HudaqAO: \r
+ case HudaqEnc: return PCT7303BEncSetParameter(DevRecord,channel,param,(int)value);\r
+ // case HudaqPWM:\r
+ // case HudaqCtr: \r
+ // case HudaqStep:\r
+ case HudaqIRQ: return PCT7303IRQSetParameter(DevRecord,channel,param,(int)value);\r
+ }\r
+ return HUDAQNOTSUPPORTED;\r
+}\r
+\r
+static double PCT7303GetParameter(const DeviceRecord *DevRecord, unsigned channel, HudaqParameter param)\r
+{\r
+ switch(param & HudaqSubsystemMASK)\r
+ {\r
+ case HudaqDI:\r
+ case HudaqDO: return PCT7303DIOGetParameter(channel,param);\r
+ //case HudaqAI: \r
+ //case HudaqAO: \r
+ case HudaqEnc: return PCT7303BEncGetParameter(DevRecord,channel,param);\r
+ //case HudaqPWM:\r
+ //case HudaqCtr:\r
+ //case HudaqStep:\r
+ case HudaqIRQ: return PCT7303IRQGetParameter(DevRecord,channel,param);\r
+ }\r
+ return WRONG_VALUE;\r
+}\r
+\r
+\r
+const CallTable CTPCT7303 =\r
+{\r
+ "PCT7303B", 0x1760, 0x0201,\r
+ InitPCT7303,\r
+ DonePCT7303,\r
+\r
+ PCT7303SetParameter,\r
+ PCT7303GetParameter,\r
+ NULL,\r
+\r
+ // INITIALIZE DI callers\r
+ PCT7303DIRead,\r
+ GenericDIReadBit, //Generic implementation\r
+ GenericOneDIReadMultiple,\r
+ // INITIALIZE DO callers\r
+ PCT7303DOWrite,\r
+ PCT7303DOWriteBit,\r
+ PCT7303DOWriteMultipleBits,\r
+ GenericDOWriteMultiple,\r
+ // INITIALIZE AI callers\r
+ NULL,\r
+ NULL,\r
+ // INITIALIZE AO callers\r
+ NULL, // Not available\r
+ NULL,\r
+ // INITIALIZE Enc callers\r
+ PCT7303BEncRead,\r
+ NULL,\r
+ // INITIALIZE Ctr callers\r
+ PCT7303BCtrRead,\r
+ PCT7303BCtrReset,\r
+ // INITIALIZE PWM callers\r
+ PCT7303BPWMWrite, \r
+ NULL, // Not available\r
+ NULL,\r
+ // INITIALIZE Step callers\r
+ NULL, // Not available\r
+};\r
+\r