--- 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;
}