--- a/iocBoot/iockstm/st.cmd Wed Sep 09 18:06:59 2015 +0200
+++ b/iocBoot/iockstm/st.cmd Tue Jan 19 10:54:27 2016 +0100
@@ -38,6 +38,11 @@
drvAsynIPPortConfigure(${PGC2_MC_LINK}, ${PGC2_MC_INET}, 0, 0, 0)
drvAsynIPPortConfigure(${PGC2_PC_LINK}, ${PGC2_PC_INET}, 0, 0, 0)
+#drvAsynI2CConfigure( "I2C", "/dev/i2c-1" )
+
+adcPiConfigure ("1", "1")
+var adcPiDebug 0
+
# Set asyn trace IO format
#define ASYN_TRACEIO_NODATA 0x0000
#define ASYN_TRACEIO_ASCII 0x0001
@@ -67,9 +72,14 @@
dbLoadRecords("db/pgc2.db","PORT=PGC2_MC, P=FHI4KSTM, Q=PGC2_MC")
dbLoadRecords("db/pgc2.db","PORT=PGC2_PC, P=FHI4KSTM, Q=PGC2_PC")
+#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_0,C=0")
#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_1,C=1")
-#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_2,C=2")
+dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_2,C=2")
dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_3,C=3")
+#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_4,C=4")
+#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_5,C=5")
+#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_6,C=6")
+#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_7,C=7")
iocInit()
--- a/kstmApp/Db/adcPi.db Wed Sep 09 18:06:59 2015 +0200
+++ b/kstmApp/Db/adcPi.db Tue Jan 19 10:54:27 2016 +0100
@@ -1,9 +1,10 @@
record(ai,"$(P)"){
- field(DTYP,"AdcPi")
+ field(DTYP,"adcPi")
field(DESC,"ADC Pi")
field(SCAN,"$(SCAN=1 second)")
- field(INP,"$(C)")
+ field(INP,"#C1 S$(C) @dumm")
field(LINR,"LINEAR")
- field (ESLO, "0.000154")
+ field (EGUF, "1.024")
+ field (EGUL, "-1.024")
field(EGU,"V")
}
--- a/kstmApp/src/Makefile Wed Sep 09 18:06:59 2015 +0200
+++ b/kstmApp/src/Makefile Tue Jan 19 10:54:27 2016 +0100
@@ -22,7 +22,7 @@
kstm_DBD += drvAsynIPPort.dbd
kstm_DBD += stream.dbd
kstm_DBD += adcPi.dbd
-
+#kstm_DBD += drvAsynI2C.dbd
# Add all the support libraries needed by this IOC
#kstm_LIBS += xxx
@@ -38,7 +38,10 @@
kstm_SRCS += pi_2_dht_read.c
kstm_SRCS += aSubReadDHT.c
#kstm_SRCS += dbSubReadADC.c
-kstm_SRCS += devadcpi.c
+#kstm_SRCS += devadcpi.c
+kstm_SRCS += drvAdcPi.c
+kstm_SRCS += devAdcPi.c
+#kstm_SRCS += drvAsynI2C.cpp
# Build the main IOC entry point on workstation OSs.
kstm_SRCS_DEFAULT += kstmMain.cpp
--- a/kstmApp/src/adcPi.dbd Wed Sep 09 18:06:59 2015 +0200
+++ b/kstmApp/src/adcPi.dbd Tue Jan 19 10:54:27 2016 +0100
@@ -1,1 +1,4 @@
-device(ai,CONSTANT,devAiAdcPi,"AdcPi")
+driver (adcPi)
+variable (adcPiDebug, int)
+registrar (adcPiRegister)
+device (ai, VME_IO, adcPiAi, "adcPi")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/src/devAdcPi.c Tue Jan 19 10:54:27 2016 +0100
@@ -0,0 +1,124 @@
+/** @brief device support adcPi
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <devSup.h>
+#include <recGbl.h>
+#include <alarm.h>
+#include <errlog.h>
+#include <aiRecord.h>
+#include <epicsExport.h>
+#include "drvAdcPi.h"
+
+typedef struct {
+ adcPiCard* card;
+ int signal;
+} adcPiAiPrivate;
+
+long adcPiInitRecordAi (aiRecord *record);
+long adcPiReadAi (aiRecord *record);
+long adcPiSpecialLinconvAi (aiRecord *record, int after);
+
+struct {
+ long number;
+ DEVSUPFUN report;
+ DEVSUPFUN init;
+ DEVSUPFUN init_record;
+ DEVSUPFUN get_ioint_info;
+ DEVSUPFUN read_ai;
+ DEVSUPFUN special_linconv;
+} adcPiAi = {
+ 6,
+ NULL,
+ NULL,
+ adcPiInitRecordAi,
+ NULL,
+ adcPiReadAi,
+ adcPiSpecialLinconvAi
+};
+epicsExportAddress (dset, adcPiAi);
+
+/** @brief init record
+ *
+ */
+long adcPiInitRecordAi (aiRecord *record)
+{
+ adcPiAiPrivate *priv;
+ epicsUInt16 initval;
+ adcPiCard* card;
+ int signal;
+
+ if (record->inp.type != VME_IO) {
+ errlogSevPrintf (errlogFatal, "adcPiInitRecordAi %s: illegal INP link type\n", record->name);
+ return -1;
+ }
+
+ card = adcPiOpen (record->inp.value.vmeio.card);
+ if (!card) {
+ errlogSevPrintf (errlogFatal, "adcPiInitRecordAi %s: invalid card number %d\n", record->name, record->inp.value.vmeio.card);
+ return S_dev_noDevice;
+ }
+
+ signal = record->inp.value.vmeio.signal;
+ if (signal < 0 || signal >= ADC_PI_MAX_CHANNEL) {
+ errlogSevPrintf (errlogFatal, "adcPiInitRecordAi %s: invalid signal number %d\n", record->name, signal);
+ return S_dev_badSignalNumber;
+ }
+
+ priv = (adcPiAiPrivate*) malloc (sizeof (adcPiAiPrivate));
+ if (!priv) {
+ errlogSevPrintf (errlogFatal, "adcPiInitRecordAi %s: out of memory\n", record->name);
+ return S_dev_noMemory;
+ }
+
+ priv->card = card;
+ priv->signal = signal;
+ record->dpvt = priv;
+
+ // printf(" priv at @%p [%d]\n", priv, sizeof (adcPiAiPrivate) );
+
+ adcPiSpecialLinconvAi (record, TRUE);
+ adcPiGet (card, signal, &initval);
+
+ record->rval = initval;
+ return 0;
+}
+
+long adcPiReadAi (aiRecord *record)
+{
+ adcPiAiPrivate *priv = (adcPiAiPrivate*) record->dpvt;
+ int status;
+
+ // printf("ReadAi: priv at @%p [%d]\n", priv, sizeof (adcPiAiPrivate) );
+
+ if (!priv) {
+ recGblSetSevr (record, UDF_ALARM, INVALID_ALARM);
+ errlogSevPrintf (errlogFatal, "adcPiReadAi %s: record not initialized correctly\n", record->name);
+ return -1;
+ }
+ unsigned short value;
+ status = adcPiGet (priv->card, priv->signal, &value);
+ if (status) {
+ errlogSevPrintf (errlogFatal, "adcPiReadAi %s: adcPiGet failes: error code 0x%x\n", record->name, status);
+ recGblSetSevr (record, READ_ALARM, INVALID_ALARM);
+ }
+ record->rval = value;
+ return status; // 2 do not convert
+}
+
+long adcPiSpecialLinconvAi (aiRecord *record, int after)
+{
+ if (after) {
+ // printf(" In convert ....\n");
+ // Check/Check ...
+ // MAX_CODE_12BIT / 2048 Volt
+ //record->eoff = ( 8191 * record->egul - -8192 * record->eguf) / (8191 - 8192);
+ record->eoff = 0;
+ record->eslo = 0.000250; // 205 uV (record->eguf - record->egul)/ (8191 - 8192);
+ }
+ return 0;
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/src/drvAdcPi.c Tue Jan 19 10:54:27 2016 +0100
@@ -0,0 +1,297 @@
+/** @brief driver for Pi ADC card xxx
+ *
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/i2c-dev.h>
+
+#include <epicsThread.h>
+#include <epicsTime.h>
+#include <epicsTypes.h>
+#include <devLib.h>
+#include <drvSup.h>
+#include <epicsExport.h>
+#include <errlog.h>
+
+#include <iocsh.h>
+
+#include "drvAdcPi.h"
+
+/* crc("adcPi") */
+#define MYMAGIC 1729550187U
+
+
+
+
+#define MCP3424_NEW_CONV 0x80
+#define MCP3424_CHANNEL_1 0x00
+#define MCP3424_CHANNEL_2 0x20
+#define MCP3424_CHANNEL_3 0x40
+#define MCP3424_CHANNEL_4 0x60
+#define MCP3424_CONT_CONV 0x10
+#define MCP3424_ONE_SHOT_CONV 0x00
+#define MCP3424_12BIT_240SPS 0x00
+#define MCP3424_14BIT_60SPS 0x04
+#define MCP3424_16BIT_15SPS 0x08
+#define MCP3424_18BIT_3_75SPS 0x0c
+#define MCP3424_GAIN_1 0x00
+#define MCP3424_GAIN_2 0x01
+#define MCP3424_GAIN_4 0x02
+#define MCP3424_GAIN_8 0x03
+#define MCP3424_CONT_MASK 0x6f
+
+// adcPi definitions, on i2c-bus
+#define ADC_1 0x68
+#define ADC_2 0x69
+#define ADC_CHANNEL1 (MCP3424_NEW_CONV | MCP3424_CHANNEL_1 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
+#define ADC_CHANNEL2 (MCP3424_NEW_CONV | MCP3424_CHANNEL_2 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
+#define ADC_CHANNEL3 (MCP3424_NEW_CONV | MCP3424_CHANNEL_3 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
+#define ADC_CHANNEL4 (MCP3424_NEW_CONV | MCP3424_CHANNEL_4 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
+
+/** @brief linked list of card structures
+ *
+ */
+struct adcPiCard {
+ epicsUInt32 magic;
+ adcPiCard *next;
+ int cardNumber;
+ unsigned int i2cAddress;
+ char* baseAddress; // not used with i2c
+ unsigned int fh; // file handle
+
+};
+static adcPiCard *firstCard = NULL;
+
+int adcPiDebug = 1;
+epicsExportAddress (int, adcPiDebug);
+
+static long adcPiReport (int detail);
+
+typedef struct {
+ long number;
+ DRVSUPFUN report;
+ DRVSUPFUN init;
+} drvAdcPi_drvet;
+drvAdcPi_drvet adcPi = {
+ 2,
+ adcPiReport,
+ NULL
+};
+
+epicsExportAddress (drvet, adcPi);
+
+static epicsUInt16 getAdc(adcPiCard* card, int signal)
+{
+static __u8 res[4];
+static unsigned int dummy;
+static __u8 adc, adc_channel;
+static int ret;
+//static unsigned int threadPrio;
+//epicsTimeStamp startTime, endTime;
+//double elapsedTime;
+//static int loopCounter;
+
+ if (signal < 0 || signal > ADC_PI_MAX_CHANNEL) {
+ errMessage (-1, "Signal Number out of range");
+ return 0;
+ }
+ //threadPrio = epicsThreadGetPrioritySelf();
+ //epicsThreadSetPriority( epicsThreadGetIdSelf(),epicsThreadPriorityMin );
+
+ //printf(" card->fh : %d, signal : %d (prio: %d)\n", card->fh, signal, epicsThreadGetPrioritySelf());
+
+ switch (signal){
+ case 0: { adc=ADC_1; adc_channel=ADC_CHANNEL1; }; break;
+ case 1: { adc=ADC_1; adc_channel=ADC_CHANNEL2; }; break;
+ case 2: { adc=ADC_1; adc_channel=ADC_CHANNEL3; }; break;
+ case 3: { adc=ADC_1; adc_channel=ADC_CHANNEL4; }; break;
+ case 4: { adc=ADC_2; adc_channel=ADC_CHANNEL1; }; break;
+ case 5: { adc=ADC_2; adc_channel=ADC_CHANNEL2; }; break;
+ case 6: { adc=ADC_2; adc_channel=ADC_CHANNEL3; }; break;
+ case 7: { adc=ADC_2; adc_channel=ADC_CHANNEL4; }; break;
+ default: { adc=ADC_1; adc_channel=ADC_CHANNEL1; }; break;
+ }
+
+
+ // choose device
+ if (ioctl(card->fh,I2C_SLAVE,adc) != 0) errMessage (0, "ioctl failed");
+ //if (usleep (50000) < 0) errMessage (0, "usleep failed");
+ //printf ("adc_channel = 0x%02X \n", adc_channel);
+ //epicsTimeGetCurrent(&startTime);
+ if (i2c_smbus_write_byte (card->fh, adc_channel) != 0) errMessage (0, "i2c_smbus_write_byte failed");
+ // wait a little bit for end of conversion
+ if (usleep (50000) < 0) errMessage (0, "usleep failed");
+ // 3 for != 18bit mode
+ //loopCounter = 0;
+ do {
+ ret = i2c_smbus_read_i2c_block_data(card->fh, adc_channel, 3, res);
+ // printf(" res[0] = 0x%02X, res[1] = 0x%02X, res[2] = 0x%02X\n", res[0], res[1], res[2]);
+ if (ret != 3) {
+ errMessage (0, "i2c_smbus_read_i2c_block_data");
+ fprintf (stderr, "i2c_smbus_read_i2c_block_data returns %d bytes != 3\n", ret);
+ }
+ //if (res[2] & 0x80) {
+ // fprintf (stderr, "i2c_smbus_read_i2c_block_data, output register (0x%02X) not updated yet\n", res[2]);
+ //}
+ //loopCounter++;
+ } while (res[2] & 0x80);
+
+ //epicsTimeGetCurrent(&endTime);
+ //elapsedTime = epicsTimeDiffInSeconds(&endTime, &startTime);
+ //printf("Elapsed time %f\n", elapsedTime);
+ //printf(" res[0] = 0x%02X, res[1] = 0x%02X, res[2] = 0x%02X, loopCounter = %d\n", res[0], res[1], res[2], loopCounter);
+
+
+ dummy = (res[0]<<8|res[1]);
+ if (dummy>=32768) dummy=65536-dummy;
+ //val = dummy * 0.000154;
+ // printf(" dummy = %d, val = %lf\n", dummy, val);
+ //return val;
+ //if (adcPiDebug) printf ("dummy = 0x%x\n", dummy);
+ // epicsThreadSetPriority( epicsThreadGetIdSelf(), threadPrio);
+ return dummy;
+}
+
+
+/** @brief configure function
+ *
+ * The configure function is called from the startup script
+ */
+int adcPiConfigure (int cardNumber, unsigned int i2cAddress)
+{
+ // long status;
+ // volatile void* baseAddress;
+ // char id[6];
+ adcPiCard **pCard;
+
+ /** @brief Check card number for sanity */
+ if (cardNumber != 1) {
+ fprintf (stderr, "adcPiConfigure: cardNumber %d must be 1\n", cardNumber);
+ return S_dev_noDevice;
+ }
+
+ /** @brief Find end of card list and check for duplicates */
+ for (pCard = &firstCard; *pCard; pCard=&(*pCard)->next) {
+ if ((*pCard)->cardNumber == cardNumber) {
+ fprintf (stderr, "adcPiConfigure: cardnumber %d already in use\n", cardNumber);
+ return S_dev_identifyOverlap;
+ }
+ } // pCard points to the end of the list
+
+
+ /** @brief Check address for sanity
+ *
+ * We use /dev/i2c-1, should be fixed/solved, so a "1" should be used*/
+ if (i2cAddress != 1) {
+ fprintf (stderr, "adcPiConfigure: i2cAddress %d must be 1\n", i2cAddress);
+ return S_dev_noDevice;
+ }
+
+ // check VMEaddress for sanity
+
+ // translate address to local address, check for overlap
+
+ // check that correct hardware is installed, devReadProbe
+ // read i2c?
+
+ /** @brief create new card structure
+ *
+ */
+ *pCard = malloc (sizeof(adcPiCard));
+ if (!*pCard) {
+ fprintf (stderr, "adcPiConfigure: out of memory\n");
+ return S_dev_noMemory;
+ }
+
+ (*pCard)->fh = open("/dev/i2c-1", O_RDWR); // "1" hardcoded!
+ if ((*pCard)->fh <= 0) {
+ fprintf (stderr, "adcPiConfigure: could not open /dev/i2c-1\n");
+ return S_dev_noDevice;
+ }
+
+ (*pCard)->magic = MYMAGIC;
+ (*pCard)->next = NULL;
+ (*pCard)->cardNumber = cardNumber;
+ (*pCard)->i2cAddress = i2cAddress;
+
+ return 0;
+}
+
+adcPiCard* adcPiOpen (int cardNumber)
+{
+ adcPiCard* card;
+ for (card = firstCard; card; card=card->next)
+ if (card->cardNumber == cardNumber) return card;
+ return NULL;
+}
+
+int adcPiGet (adcPiCard* card, int signal, epicsUInt16* pValue)
+{
+
+ if (adcPiDebug>1)
+ printf("adcPiGet card %d signal %d (adcPiDebug: %d)\n",
+ card->cardNumber, signal, adcPiDebug);
+
+ if (!card) return S_dev_noDevice;
+ if (card->magic != MYMAGIC) return S_dev_wrongDevice;
+
+ if (signal < 0 || signal > ADC_PI_MAX_CHANNEL) return S_dev_badSignalNumber;
+
+ *pValue = getAdc(card, signal);
+
+ if (adcPiDebug>1)
+ printf("adcPiGet card %d signal %d @%p = 0x%4X\n",
+ card->cardNumber, signal, (void *)&getAdc, (epicsUInt16)*pValue);
+ return 0;
+}
+
+/** @brief report function
+ *
+ */
+static long adcPiReport (int detail)
+{
+ adcPiCard *card;
+ for (card = firstCard; card; card = card->next) {
+ printf (" card %d at address %p \n", card->cardNumber, card->baseAddress);
+ if (detail >= 1) {
+ int signal;
+ unsigned short value;
+ for (signal = 0; signal < ADC_PI_MAX_CHANNEL; signal++) {
+ value = getAdc(card, signal);
+ printf(" ADC %d = 0x%04x = %+8.4f V\n", signal, value, value * 0.000154); // tobedef
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+
+static const iocshArg adcPiConfigureArg0 = { "cardNumber", iocshArgInt };
+static const iocshArg adcPiConfigureArg1 = { "i2cAddress", iocshArgInt };
+
+static const iocshArg * const adcPiConfigureArgs[] = {
+ &adcPiConfigureArg0,
+ &adcPiConfigureArg1
+};
+static const iocshFuncDef adcPiConfigureDef = { "adcPiConfigure", 2, adcPiConfigureArgs };
+static void adcPiConfigureFunc (const iocshArgBuf *args)
+{
+ adcPiConfigure (args[0].ival, args[1].ival);
+}
+
+static void adcPiRegister ()
+{
+ iocshRegister (&adcPiConfigureDef, adcPiConfigureFunc);
+}
+
+epicsExportRegistrar (adcPiRegister);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/src/drvAdcPi.h Tue Jan 19 10:54:27 2016 +0100
@@ -0,0 +1,35 @@
+#ifndef drvAdcPi_h
+#define drvAdcPi_h
+#include <epicsTypes.h>
+#include <devLib.h>
+
+
+#define ADC_PI_MAX_CHANNEL 8
+
+#define MAX_CODE_12BIT 8191
+
+/** @brief Initialize the card
+ *
+ * Initialize the card(called from startup script)
+ */
+int adcPiConfigure (int cardnumber, unsigned int i2cAddress);
+
+/** @brief card handle
+ *
+ * Define a type for the card handle
+ */
+typedef struct adcPiCard adcPiCard;
+
+/** @brief open card
+ *
+ * Get card handle for card number
+ */
+adcPiCard* adcPiOpen (int cardnumber);
+
+/** @brief get values
+ *
+ * Read values from channels
+ */
+int adcPiGet (adcPiCard* card, int signal, epicsUInt16* pvalue);
+
+#endif
\ No newline at end of file