Add adcPi device support
authorHeinz Junkes <junkes@fhi-berlin.mpg.de>
Wed, 09 Sep 2015 18:06:59 +0200
changeset 1 7029db7ac3db
parent 0 bd6bb22c6533
child 2 3b3af1ff2783
Add adcPi device support
iocBoot/iockstm/Makefile
iocBoot/iockstm/st.cmd
kstmApp/Db/Makefile
kstmApp/Db/adcPi.db
kstmApp/Db/dht.db
kstmApp/src/Makefile
kstmApp/src/aSubReadDHT.c
kstmApp/src/aSubReadDHT.dbd
kstmApp/src/adcPi.dbd
kstmApp/src/devadcpi.c
kstmApp/src/pi_2_dht_read.c
--- a/iocBoot/iockstm/Makefile	Fri Aug 14 11:30:43 2015 +0200
+++ b/iocBoot/iockstm/Makefile	Wed Sep 09 18:06:59 2015 +0200
@@ -1,5 +1,5 @@
 TOP = ../..
 include $(TOP)/configure/CONFIG
-ARCH = linux-x86_64
+ARCH = linux-arm 
 TARGETS = envPaths
 include $(TOP)/configure/RULES.ioc
--- a/iocBoot/iockstm/st.cmd	Fri Aug 14 11:30:43 2015 +0200
+++ b/iocBoot/iockstm/st.cmd	Wed Sep 09 18:06:59 2015 +0200
@@ -53,12 +53,12 @@
 # ASYN_TRACE_FLOW     0x0010
 #asynSetTraceMask ${PGC2_MC_LINK} 0 8
 
-epicsEnvSet ("streamDebug","1")
+#epicsEnvSet ("streamDebug","1")
 
 ## Load record instances
 dbLoadRecords("db/misc.db","P=FHI4KSTM, Q=MISC")
 
-#dbLoadRecords("db/dht.db","P=FHI4KSTM, Q=DHT")
+dbLoadRecords("db/dht.db","P=FHI4KSTM, Q=DHT")
 
 dbLoadTemplate("db/4kStmEuro.sub")
 
@@ -67,6 +67,10 @@
 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_1,C=1")
+#dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_2,C=2")
+dbLoadRecords("db/adcPi.db","P=FHI4KSTM:ADCPI:CH_3,C=3")
+
 iocInit()
 
 ## Start any sequence programs
--- a/kstmApp/Db/Makefile	Fri Aug 14 11:30:43 2015 +0200
+++ b/kstmApp/Db/Makefile	Wed Sep 09 18:06:59 2015 +0200
@@ -13,7 +13,9 @@
 #DB += xxx.db
 DB += dht.db
 DB += misc.db
+
 DB += mtm.db
+DB += mtm.proto
 
 DB += 4kStmEuro.sub
 DB += eurotherm2k.proto
@@ -25,6 +27,8 @@
 DB += M1900.db
 DB += M1900.proto
 
+DB += adcPi.db
+
 #----------------------------------------------------
 # If <anyname>.db template is not named <anyname>*.template add
 # <anyname>_template = <templatename>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/Db/adcPi.db	Wed Sep 09 18:06:59 2015 +0200
@@ -0,0 +1,9 @@
+record(ai,"$(P)"){
+  field(DTYP,"AdcPi")
+  field(DESC,"ADC Pi")
+  field(SCAN,"$(SCAN=1 second)")
+  field(INP,"$(C)")
+  field(LINR,"LINEAR")
+  field (ESLO, "0.000154")
+  field(EGU,"V")
+}
--- a/kstmApp/Db/dht.db	Fri Aug 14 11:30:43 2015 +0200
+++ b/kstmApp/Db/dht.db	Wed Sep 09 18:06:59 2015 +0200
@@ -1,8 +1,14 @@
-record(sub,"$(P):$(Q):R_temp")
+record(aSub,"$(P):$(Q):R_DHT")
 {
-    field(INAM,"dbSubReadDHTInit")
-    field(SNAM,"dbSubReadDHTProcess")
-    field(SCAN,"5 second")
-    field(INPA,"3")
+  field(DESC, "Reads DHT from GPIO def in A")
+  field(INAM,"aSubReadDHTInit")
+  field(SNAM,"aSubReadDHTProcess")
+  field(SCAN,"10 second")
+  field(INPA,"4")
+  field(FTA, "USHORT")
+# Temperature in VALA
+  field(FTVA, "DOUBLE")
+# Humidity in VALB
+  field(FTVB, "DOUBLE")
 }
 
--- a/kstmApp/src/Makefile	Fri Aug 14 11:30:43 2015 +0200
+++ b/kstmApp/src/Makefile	Wed Sep 09 18:06:59 2015 +0200
@@ -17,10 +17,12 @@
 
 # Include dbd files from all support applications:
 #kstm_DBD += xxx.dbd
-kstm_DBD += dbSubReadDHT.dbd 
+kstm_DBD += aSubReadDHT.dbd 
 kstm_DBD += asyn.dbd
 kstm_DBD += drvAsynIPPort.dbd
 kstm_DBD += stream.dbd
+kstm_DBD += adcPi.dbd
+
 
 # Add all the support libraries needed by this IOC
 #kstm_LIBS += xxx 
@@ -34,8 +36,9 @@
 kstm_SRCS += common_dht_read.c
 kstm_SRCS += pi_2_mmio.c
 kstm_SRCS += pi_2_dht_read.c
-kstm_SRCS += dbSubReadDHT.c
+kstm_SRCS += aSubReadDHT.c
 #kstm_SRCS += dbSubReadADC.c
+kstm_SRCS += devadcpi.c
 
 # Build the main IOC entry point on workstation OSs.
 kstm_SRCS_DEFAULT += kstmMain.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/src/aSubReadDHT.c	Wed Sep 09 18:06:59 2015 +0200
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <dbDefs.h>
+#include <registryFunction.h>
+#include <subRecord.h>
+#include <aSubRecord.h>
+#include <epicsExport.h>
+
+#include "pi_2_dht_read.h"
+
+#define USED_DHT_TYPE 22
+int aSubReadDHTDebug = 0;
+unsigned short GPIOPin;
+
+static long aSubReadDHTInit(aSubRecord *precord)
+{
+unsigned short *a;
+
+  if (aSubReadDHTDebug)
+    printf("Record %s called aSubReadDHTInit(%p)\n", precord->name, (void*) precord);
+
+  a = (unsigned short *)precord->a; 
+  GPIOPin = a[0];
+
+  if (aSubReadDHTDebug)
+    printf("Record %s : GPIOPin = %d\n", precord->name, GPIOPin);
+
+  return 0;
+}
+
+static long aSubReadDHTProcess(aSubRecord *precord)
+{
+float humidity, temperature;
+int ret;
+double *vala, *valb;
+
+  if (aSubReadDHTDebug)
+    printf("Record %s called aSubRreadDHTProcess(%p)\n", precord->name, (void*) precord);
+
+  ret = pi_2_dht_read(USED_DHT_TYPE, GPIOPin, &humidity, &temperature);
+
+  if (aSubReadDHTDebug)
+    printf(" ret : %d, humidity = %f, temperature = %f\n", ret, humidity, temperature);
+
+  if (!ret) {
+    vala = (double *)precord->vala;
+    valb = (double *)precord->valb;
+    vala[0] = (double)temperature;
+    valb[0] = (double)humidity;
+  }
+  return 0;
+}
+
+/* Register these symbols for use by IOC code: */
+
+epicsExportAddress(int, aSubReadDHTDebug);
+epicsRegisterFunction(aSubReadDHTInit);
+epicsRegisterFunction(aSubReadDHTProcess);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/src/aSubReadDHT.dbd	Wed Sep 09 18:06:59 2015 +0200
@@ -0,0 +1,3 @@
+variable(aSubReadDHTDebug)
+function(aSubReadDHTInit)
+function(aSubReadDHTProcess)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/src/adcPi.dbd	Wed Sep 09 18:06:59 2015 +0200
@@ -0,0 +1,1 @@
+device(ai,CONSTANT,devAiAdcPi,"AdcPi")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kstmApp/src/devadcpi.c	Wed Sep 09 18:06:59 2015 +0200
@@ -0,0 +1,117 @@
+#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 <epicsExport.h>
+#include <dbAccess.h>
+#include <devSup.h>
+#include <recGbl.h>
+
+#include <aiRecord.h>
+
+// ADCPi definitions
+#define ADC_1 		0x68
+#define ADC_2 		0x69
+#define ADC_CHANNEL1	0x98
+#define ADC_CHANNEL2	0xB8
+#define ADC_CHANNEL3 	0xD8
+#define ADC_CHANNEL4	0xF8
+
+
+static long init_record(aiRecord *pai);
+static long read_ai(aiRecord *pai);
+
+struct adcPiChannel {
+  unsigned int channel;
+};
+
+
+int getadc (int chn){
+  unsigned int fh,dummy, adc, adc_channel;
+//  double val;
+  __u8  res[4];
+printf(" Read channel Nr: %d\n", chn);
+  switch (chn){
+    case 1: { adc=ADC_1; adc_channel=ADC_CHANNEL1; }; break;
+    case 2: { adc=ADC_1; adc_channel=ADC_CHANNEL2; }; break;
+    case 3: { adc=ADC_1; adc_channel=ADC_CHANNEL3; }; break;
+    case 4: { adc=ADC_1; adc_channel=ADC_CHANNEL4; }; break;
+    case 5: { adc=ADC_2; adc_channel=ADC_CHANNEL1; }; break;
+    case 6: { adc=ADC_2; adc_channel=ADC_CHANNEL2; }; break;
+    case 7: { adc=ADC_2; adc_channel=ADC_CHANNEL3; }; break;
+    case 8: { adc=ADC_2; adc_channel=ADC_CHANNEL4; }; break;
+    default: { adc=ADC_1; adc_channel=ADC_CHANNEL1; }; break;
+  }
+  fh = open("/dev/i2c-1", O_RDWR);
+  ioctl(fh,I2C_SLAVE,adc);
+  i2c_smbus_write_byte (fh, adc_channel);
+  usleep (50000);
+  i2c_smbus_read_i2c_block_data(fh,adc_channel,4,res);
+  usleep(50000);
+  close (fh);
+  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;
+  return dummy;
+}
+
+static long init_record(aiRecord *pai)
+{
+  struct adcPiChannel* priv;
+  unsigned long channel;
+
+  priv=malloc(sizeof(struct adcPiChannel));
+  if(!priv){
+    recGblRecordError(S_db_noMemory, (void*)pai,
+      "devAoTimebase failed to allocate private struct");
+    return S_db_noMemory;
+  }
+
+  recGblInitConstantLink(&pai->inp,DBF_ULONG,&channel);
+
+  priv->channel=channel;
+  pai->dpvt=priv;
+
+  return 0;
+}
+
+
+static long read_ai(aiRecord *pai)
+{
+  struct adcPiChannel* priv=pai->dpvt;
+
+  pai->rval = getadc(priv->channel);
+
+  return 0;
+}
+
+struct {
+  long num;
+  DEVSUPFUN  report;
+  DEVSUPFUN  init;
+  DEVSUPFUN  init_record;
+  DEVSUPFUN  get_ioint_info;
+  DEVSUPFUN  read_ai;
+  DEVSUPFUN  special_linconv;
+} devAiAdcPi = {
+  6, /* space for 6 functions */
+  NULL,
+  NULL,
+  init_record,
+  NULL,
+  read_ai,
+  NULL
+};
+
+epicsExportAddress(dset,devAiAdcPi);
+
--- a/kstmApp/src/pi_2_dht_read.c	Fri Aug 14 11:30:43 2015 +0200
+++ b/kstmApp/src/pi_2_dht_read.c	Wed Sep 09 18:06:59 2015 +0200
@@ -21,6 +21,10 @@
 #include <stdbool.h>
 #include <stdlib.h>
 
+#include "epicsExit.h"
+#include "epicsThread.h"
+#include "iocsh.h"
+
 #include "pi_2_dht_read.h"
 #include "pi_2_mmio.h"
 
@@ -36,6 +40,11 @@
 #define DHT_PULSES 41
 
 int pi_2_dht_read(int type, int pin, float* humidity, float* temperature) {
+int i;
+volatile int j;
+unsigned int defPrio;
+epicsThreadId threadIdSelf;
+
   // Validate humidity and temperature arguments and set them to zero.
   if (humidity == NULL || temperature == NULL) {
     return DHT_ERROR_ARGUMENT;
@@ -56,7 +65,9 @@
   pi_2_mmio_set_output(pin);
 
   // Bump up process priority and change scheduler to try to try to make process more 'real time'.
-  set_max_priority();
+  defPrio = epicsThreadGetPrioritySelf();
+  threadIdSelf = epicsThreadGetIdSelf();
+  epicsThreadSetPriority( threadIdSelf , epicsThreadPriorityHigh);
 
   // Set pin high for ~500 milliseconds.
   pi_2_mmio_set_high(pin);
@@ -72,28 +83,26 @@
   // Set pin at input.
   pi_2_mmio_set_input(pin);
   // Need a very short delay before reading pins or else value is sometimes still low.
-volatile int i;
-  for (i = 0; i < 50; ++i) {
-  }
+  for (j = 0; j < 50; ++j) { }
 
   // Wait for DHT to pull pin low.
   uint32_t count = 0;
   while (pi_2_mmio_input(pin)) {
     if (++count >= DHT_MAXCOUNT) {
       // Timeout waiting for response.
-      set_default_priority();
+      epicsThreadSetPriority( threadIdSelf , defPrio);
       return DHT_ERROR_TIMEOUT;
     }
   }
 
-  // Record pulse widths for the expected result bits.
-  int j;
-  for ( j=0; j < DHT_PULSES*2; j+=2) {
+
+ // Record pulse widths for the expected result bits.
+  for ( i=0; i < DHT_PULSES*2; i+=2) {
     // Count how long pin is low and store in pulseCounts[i]
     while (!pi_2_mmio_input(pin)) {
       if (++pulseCounts[i] >= DHT_MAXCOUNT) {
         // Timeout waiting for response.
-        set_default_priority();
+        epicsThreadSetPriority( threadIdSelf , defPrio);
         return DHT_ERROR_TIMEOUT;
       }
     }
@@ -101,23 +110,22 @@
     while (pi_2_mmio_input(pin)) {
       if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
         // Timeout waiting for response.
-        set_default_priority();
+        epicsThreadSetPriority( threadIdSelf , defPrio);
         return DHT_ERROR_TIMEOUT;
       }
     }
   }
 
   // Done with timing critical code, now interpret the results.
-
   // Drop back to normal priority.
-  set_default_priority();
+  // set_default_priority();
+  epicsThreadSetPriority( threadIdSelf , defPrio);
 
   // Compute the average low pulse width to use as a 50 microsecond reference threshold.
   // Ignore the first two readings because they are a constant 80 microsecond pulse.
   uint32_t threshold = 0;
-  int k;
-  for (k=2; i < DHT_PULSES*2; k+=2) {
-    threshold += pulseCounts[k];
+  for (i=2; i < DHT_PULSES*2; i+=2) {
+    threshold += pulseCounts[i];
   }
   threshold /= DHT_PULSES-1;
 
@@ -125,11 +133,10 @@
   // If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher
   // then it must be a ~70us 1 pulse.
   uint8_t data[5] = {0};
-  int l;
-  for ( l=3; l < DHT_PULSES*2; l+=2) {
-    int index = (l-3)/16;
+  for ( i=3; i < DHT_PULSES*2; i+=2) {
+    int index = (i-3)/16;
     data[index] <<= 1;
-    if (pulseCounts[l] >= threshold) {
+    if (pulseCounts[i] >= threshold) {
       // One bit for long pulse.
       data[index] |= 1;
     }