kstmApp/src/drvAdcPi.c
changeset 2 3b3af1ff2783
equal deleted inserted replaced
1:7029db7ac3db 2:3b3af1ff2783
       
     1 /** @brief driver for Pi ADC card xxx
       
     2  *
       
     3  */
       
     4 #include <stdio.h>
       
     5 #include <stdint.h>
       
     6 #include <stdlib.h>
       
     7 #include <string.h>
       
     8 #include <errno.h>
       
     9 #include <unistd.h>
       
    10 #include <sys/types.h>
       
    11 #include <sys/stat.h>
       
    12 #include <sys/ioctl.h>
       
    13 #include <fcntl.h>
       
    14 #include <linux/i2c-dev.h>
       
    15 
       
    16 #include <epicsThread.h>
       
    17 #include <epicsTime.h>
       
    18 #include <epicsTypes.h>
       
    19 #include <devLib.h>
       
    20 #include <drvSup.h>
       
    21 #include <epicsExport.h>
       
    22 #include <errlog.h>
       
    23 
       
    24 #include <iocsh.h>
       
    25 
       
    26 #include "drvAdcPi.h"
       
    27 
       
    28 /* crc("adcPi") */
       
    29 #define MYMAGIC 1729550187U 
       
    30 
       
    31 
       
    32 
       
    33 
       
    34 #define MCP3424_NEW_CONV  0x80
       
    35 #define MCP3424_CHANNEL_1 0x00
       
    36 #define MCP3424_CHANNEL_2 0x20
       
    37 #define MCP3424_CHANNEL_3 0x40
       
    38 #define MCP3424_CHANNEL_4 0x60
       
    39 #define MCP3424_CONT_CONV 0x10
       
    40 #define MCP3424_ONE_SHOT_CONV 0x00
       
    41 #define MCP3424_12BIT_240SPS 0x00
       
    42 #define MCP3424_14BIT_60SPS 0x04
       
    43 #define MCP3424_16BIT_15SPS 0x08
       
    44 #define MCP3424_18BIT_3_75SPS 0x0c
       
    45 #define MCP3424_GAIN_1 0x00
       
    46 #define MCP3424_GAIN_2 0x01
       
    47 #define MCP3424_GAIN_4 0x02
       
    48 #define MCP3424_GAIN_8 0x03
       
    49 #define MCP3424_CONT_MASK 0x6f
       
    50  
       
    51 // adcPi definitions, on i2c-bus
       
    52 #define ADC_1 		0x68
       
    53 #define ADC_2 		0x69
       
    54 #define ADC_CHANNEL1	(MCP3424_NEW_CONV | MCP3424_CHANNEL_1 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
       
    55 #define ADC_CHANNEL2	(MCP3424_NEW_CONV | MCP3424_CHANNEL_2 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
       
    56 #define ADC_CHANNEL3	(MCP3424_NEW_CONV | MCP3424_CHANNEL_3 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
       
    57 #define ADC_CHANNEL4	(MCP3424_NEW_CONV | MCP3424_CHANNEL_4 | MCP3424_CONT_CONV | MCP3424_14BIT_60SPS | MCP3424_GAIN_1 )
       
    58 
       
    59 /** @brief linked list of card structures
       
    60  *
       
    61  */
       
    62 struct adcPiCard {
       
    63 	epicsUInt32 magic;
       
    64 	adcPiCard *next;
       
    65 	int cardNumber;
       
    66 	unsigned int i2cAddress;
       
    67 	char* baseAddress; // not used with i2c
       
    68 	unsigned int fh; // file handle
       
    69 
       
    70 };
       
    71 static adcPiCard *firstCard = NULL;
       
    72 
       
    73 int adcPiDebug = 1;
       
    74 epicsExportAddress (int, adcPiDebug);
       
    75 
       
    76 static long adcPiReport (int detail);
       
    77 
       
    78 typedef struct {
       
    79 	long 		number;
       
    80 	DRVSUPFUN	report;
       
    81 	DRVSUPFUN	init;
       
    82 } drvAdcPi_drvet;
       
    83 drvAdcPi_drvet adcPi = {
       
    84 	2,
       
    85 	adcPiReport,
       
    86 	NULL
       
    87 };
       
    88 
       
    89 epicsExportAddress (drvet, adcPi);
       
    90 
       
    91 static epicsUInt16 getAdc(adcPiCard* card, int signal)
       
    92 {
       
    93 static __u8  res[4];
       
    94 static unsigned int dummy; 
       
    95 static __u8 adc, adc_channel;
       
    96 static int ret;
       
    97 //static unsigned int threadPrio;
       
    98 //epicsTimeStamp startTime, endTime;
       
    99 //double elapsedTime;
       
   100 //static int loopCounter;
       
   101 
       
   102 	if (signal < 0 || signal > ADC_PI_MAX_CHANNEL) {
       
   103 		errMessage (-1, "Signal Number out of range");
       
   104 		return 0;
       
   105 	}
       
   106 	//threadPrio = epicsThreadGetPrioritySelf();
       
   107 	//epicsThreadSetPriority( epicsThreadGetIdSelf(),epicsThreadPriorityMin );
       
   108 	
       
   109 	//printf(" card->fh : %d, signal : %d (prio: %d)\n", card->fh, signal, epicsThreadGetPrioritySelf());
       
   110 	
       
   111 	switch (signal){
       
   112     	case 0: { adc=ADC_1; adc_channel=ADC_CHANNEL1; }; break;
       
   113 		case 1: { adc=ADC_1; adc_channel=ADC_CHANNEL2; }; break;
       
   114 		case 2: { adc=ADC_1; adc_channel=ADC_CHANNEL3; }; break;
       
   115 		case 3: { adc=ADC_1; adc_channel=ADC_CHANNEL4; }; break;
       
   116 		case 4: { adc=ADC_2; adc_channel=ADC_CHANNEL1; }; break;
       
   117 		case 5: { adc=ADC_2; adc_channel=ADC_CHANNEL2; }; break;
       
   118 		case 6: { adc=ADC_2; adc_channel=ADC_CHANNEL3; }; break;
       
   119 		case 7: { adc=ADC_2; adc_channel=ADC_CHANNEL4; }; break;
       
   120 		default: { adc=ADC_1; adc_channel=ADC_CHANNEL1; }; break;
       
   121 	}
       
   122 
       
   123 		
       
   124 	// choose device
       
   125 	if (ioctl(card->fh,I2C_SLAVE,adc) != 0) errMessage (0, "ioctl failed");
       
   126 	//if (usleep (50000) < 0) errMessage (0, "usleep failed");
       
   127 	//printf ("adc_channel = 0x%02X \n", adc_channel);
       
   128 	//epicsTimeGetCurrent(&startTime);
       
   129 	if (i2c_smbus_write_byte (card->fh, adc_channel) != 0) errMessage (0, "i2c_smbus_write_byte failed");
       
   130 	// wait a little bit for end of conversion
       
   131 	if (usleep (50000) < 0) errMessage (0, "usleep failed");
       
   132 	// 3 for != 18bit mode
       
   133 	//loopCounter = 0;
       
   134 	do {
       
   135 		ret = i2c_smbus_read_i2c_block_data(card->fh, adc_channel, 3, res);
       
   136 		// printf(" res[0] = 0x%02X, res[1] = 0x%02X, res[2] = 0x%02X\n", res[0], res[1], res[2]);
       
   137 		if (ret != 3) {
       
   138 			errMessage (0, "i2c_smbus_read_i2c_block_data");
       
   139 			fprintf (stderr, "i2c_smbus_read_i2c_block_data returns %d bytes != 3\n", ret);
       
   140 		}
       
   141 		//if (res[2] & 0x80) {
       
   142 		//	fprintf (stderr, "i2c_smbus_read_i2c_block_data, output register (0x%02X) not updated yet\n", res[2]);
       
   143 		//}
       
   144 		//loopCounter++;
       
   145 	} while (res[2] & 0x80);
       
   146 		
       
   147 	//epicsTimeGetCurrent(&endTime);
       
   148 	//elapsedTime = epicsTimeDiffInSeconds(&endTime, &startTime);
       
   149 	//printf("Elapsed time %f\n", elapsedTime);
       
   150 	//printf(" res[0] = 0x%02X, res[1] = 0x%02X, res[2] = 0x%02X, loopCounter = %d\n", res[0], res[1], res[2], loopCounter);
       
   151     
       
   152     
       
   153     dummy = (res[0]<<8|res[1]);
       
   154 	if (dummy>=32768) dummy=65536-dummy;
       
   155 	//val = dummy * 0.000154;
       
   156 	// printf(" dummy = %d, val = %lf\n", dummy, val);
       
   157 	//return val;
       
   158 	//if (adcPiDebug) printf ("dummy = 0x%x\n", dummy);
       
   159 	// epicsThreadSetPriority( epicsThreadGetIdSelf(), threadPrio);
       
   160 	return dummy;
       
   161 }
       
   162 
       
   163 
       
   164 /** @brief configure function
       
   165  *
       
   166  * The configure function is called from the startup script
       
   167  */
       
   168 int adcPiConfigure (int cardNumber, unsigned int i2cAddress)
       
   169 {
       
   170 	// long status;
       
   171 	// volatile void* baseAddress;
       
   172 	// char id[6];
       
   173 	adcPiCard **pCard;
       
   174 	
       
   175 	/** @brief Check card number for sanity */
       
   176 	if (cardNumber != 1) {
       
   177 		fprintf (stderr, "adcPiConfigure: cardNumber %d must be 1\n", cardNumber);
       
   178 		return S_dev_noDevice;
       
   179 	}
       
   180 	
       
   181 	/** @brief Find end of card list and check for duplicates */
       
   182 	for (pCard = &firstCard; *pCard; pCard=&(*pCard)->next) {
       
   183 		if ((*pCard)->cardNumber == cardNumber) {
       
   184 			fprintf (stderr, "adcPiConfigure: cardnumber %d already in use\n", cardNumber);
       
   185 			return S_dev_identifyOverlap;
       
   186 		}
       
   187 	} // pCard points to the end of the list
       
   188 
       
   189 
       
   190     /** @brief Check address for sanity
       
   191      *
       
   192      * We use /dev/i2c-1, should be fixed/solved, so a "1" should be used*/
       
   193 	if (i2cAddress != 1) {
       
   194 		fprintf (stderr, "adcPiConfigure: i2cAddress %d must be 1\n", i2cAddress);
       
   195 		return S_dev_noDevice;
       
   196 	}
       
   197 
       
   198 	// check VMEaddress for sanity
       
   199 	
       
   200 	// translate address to local address, check for overlap
       
   201 	
       
   202 	// check that correct hardware is installed, devReadProbe
       
   203 	// read i2c?
       
   204 	
       
   205 	/** @brief create new card structure
       
   206 	 *
       
   207 	 */
       
   208 	 *pCard = malloc (sizeof(adcPiCard));
       
   209 	 if (!*pCard) {
       
   210 		 fprintf (stderr, "adcPiConfigure: out of memory\n");
       
   211 		 return S_dev_noMemory;
       
   212 	 }
       
   213 	 
       
   214 	 (*pCard)->fh = open("/dev/i2c-1", O_RDWR); // "1" hardcoded!
       
   215 	 if ((*pCard)->fh <= 0) {
       
   216 		fprintf (stderr, "adcPiConfigure: could not open /dev/i2c-1\n");
       
   217 		return S_dev_noDevice;
       
   218 	}
       
   219 
       
   220 	(*pCard)->magic = MYMAGIC;
       
   221 	(*pCard)->next = NULL;
       
   222 	(*pCard)->cardNumber = cardNumber;
       
   223 	(*pCard)->i2cAddress = i2cAddress;
       
   224 	
       
   225 	return 0;
       
   226 }
       
   227 
       
   228 adcPiCard* adcPiOpen (int cardNumber)
       
   229 {
       
   230 	adcPiCard* card;
       
   231 	for (card = firstCard; card; card=card->next)
       
   232 		if (card->cardNumber == cardNumber) return card;
       
   233 	return NULL;
       
   234 }
       
   235 
       
   236 int adcPiGet (adcPiCard* card, int signal, epicsUInt16* pValue)
       
   237 {
       
   238 	
       
   239 	if (adcPiDebug>1)
       
   240 		printf("adcPiGet card %d signal %d (adcPiDebug: %d)\n",
       
   241 		  card->cardNumber, signal, adcPiDebug);
       
   242 	
       
   243 	if (!card) return S_dev_noDevice;
       
   244 	if (card->magic != MYMAGIC) return S_dev_wrongDevice;
       
   245 		
       
   246 	if (signal < 0 || signal > ADC_PI_MAX_CHANNEL) return S_dev_badSignalNumber;
       
   247 		
       
   248 	*pValue = getAdc(card, signal);
       
   249 	
       
   250 	if (adcPiDebug>1)
       
   251 		printf("adcPiGet card %d signal %d @%p = 0x%4X\n",
       
   252 		  card->cardNumber, signal, (void *)&getAdc, (epicsUInt16)*pValue);
       
   253 	return 0;
       
   254 }
       
   255 
       
   256 /** @brief report function
       
   257  *
       
   258  */
       
   259 static long adcPiReport (int detail)
       
   260 {
       
   261 	adcPiCard *card;
       
   262 	for (card = firstCard; card; card = card->next) {
       
   263 		printf ("  card %d at address %p \n", card->cardNumber, card->baseAddress);
       
   264 		if (detail >= 1) {
       
   265 			int signal;
       
   266 			unsigned short value;
       
   267 			for (signal = 0; signal < ADC_PI_MAX_CHANNEL; signal++) {
       
   268 				value = getAdc(card, signal);
       
   269 				printf("     ADC %d = 0x%04x = %+8.4f V\n", signal, value, value * 0.000154); // tobedef
       
   270 			}
       
   271 		}
       
   272 	}
       
   273 	return 0;
       
   274 }
       
   275 
       
   276 
       
   277 
       
   278 
       
   279 static const iocshArg adcPiConfigureArg0 = { "cardNumber", iocshArgInt };
       
   280 static const iocshArg adcPiConfigureArg1 = { "i2cAddress", iocshArgInt };
       
   281 
       
   282 static const iocshArg * const adcPiConfigureArgs[] = {
       
   283 	&adcPiConfigureArg0,
       
   284 	&adcPiConfigureArg1
       
   285 };
       
   286 static const iocshFuncDef adcPiConfigureDef = { "adcPiConfigure", 2, adcPiConfigureArgs };
       
   287 static void adcPiConfigureFunc (const iocshArgBuf *args)
       
   288 {
       
   289 	adcPiConfigure (args[0].ival, args[1].ival);
       
   290 }
       
   291 
       
   292 static void adcPiRegister ()
       
   293 {
       
   294 	iocshRegister (&adcPiConfigureDef, adcPiConfigureFunc);
       
   295 }
       
   296 
       
   297 epicsExportRegistrar (adcPiRegister);