Commit dfa91a3bc3fea741b18f1a2f3e1bb0d695444b33
1 parent
cc228d59b9
Exists in
master
libad9915 : add initial sources & include files
Showing 6 changed files with 541 additions and 0 deletions Side-by-side Diff
include/ad9915.h
| 1 | +/* | |
| 2 | +dds initialisation et SPI | |
| 3 | +*/ | |
| 4 | + | |
| 5 | +#include <stdint.h> | |
| 6 | +#include <unistd.h> | |
| 7 | +#include <stdio.h> | |
| 8 | +#include <stdlib.h> | |
| 9 | +#include <getopt.h> | |
| 10 | +#include <fcntl.h> | |
| 11 | +#include <sys/ioctl.h> | |
| 12 | +#include <linux/types.h> | |
| 13 | +#include <linux/spi/spidev.h> | |
| 14 | +/* memory management */ | |
| 15 | +#include <sys/mman.h> | |
| 16 | +#include "spi.h" | |
| 17 | +#include <string.h> | |
| 18 | +#include <math.h> | |
| 19 | +#include <time.h> | |
| 20 | + | |
| 21 | + | |
| 22 | +static const char CFRAddress[] = {0x00,0x01,0x02,0x03}; | |
| 23 | + | |
| 24 | +static const char CFR1Start[] ={0x00, 0x01, 0x00, 0x0a}; | |
| 25 | +//static const char CFR1Start[] ={0x00, 0x01, 0x01, 0x08}; //with osk enable | |
| 26 | +static const char CFR2Start[] ={0x00, 0x80, 0x09, 0x00}; //0x80 enable prof mode | |
| 27 | +static const char CFR3Start[] = {0x00, 0x00, 0x19, 0x1C}; | |
| 28 | +static const char CFR4Start[] = {0x00, 0x05, 0x21, 0x20}; | |
| 29 | + | |
| 30 | +static const char USR0Address = 0x1B; | |
| 31 | +static const char FTW0Address = 0x0b; //profile 0 ftw | |
| 32 | +static const char PA0Address = 0x0c; //profile 0 | |
| 33 | + | |
| 34 | +static const char DACCalEnable[] = {0x01, 0x05, 0x21, 0x20}; //Command to enable the DAC Cal, should be 0x01XXXXXX, where X is the last 6 digits of CFR4Start | |
| 35 | + | |
| 36 | + | |
| 37 | +void Send_Reset(int f_dds); | |
| 38 | +void Send_IO_Update (int f_dds); //Send the update to set the control registers | |
| 39 | +void write_register (int fd, unsigned char addr, unsigned char d3, unsigned char d2, unsigned char d1, unsigned char d0); | |
| 40 | +void Initialize_DDS (int fd, int f_dds); | |
| 41 | +void Calibrate_DAC(int fd, int f_dds); | |
| 42 | +void basic_setup(int fd, int f_dds, uint16_t ampWord, uint16_t phaseWord); | |
| 43 | +void modulus_setup(int fd, int f_dds); | |
| 44 | +void setFreqMM(int fd, int f_dds, unsigned int ftw, unsigned int A, unsigned int B); | |
| 45 | +void setAmpPhaseWord(int fd, int f_dds,unsigned int phaseAmpWord); | |
| 46 | +int openAndSetDdsFreq( char * device, char * gpio_update, double f_clk, double f_out, uint16_t ampWord, uint16_t phaseWord); | |
| 47 | +int receiveParameterFromPythonServer(char * device, double f_clk, double f_out); | |
| 48 | +int setDdsFreqFull ( int fd, int f_dds, double f_clk, double f_out, uint16_t ampWord, uint16_t phaseWord); | |
| 49 | + |
include/ddsFreq.h
| 1 | +#include <stdlib.h> | |
| 2 | +#include <stdio.h> | |
| 3 | +#include <unistd.h> | |
| 4 | +#include <math.h> | |
| 5 | + | |
| 6 | +struct frac | |
| 7 | +{ | |
| 8 | + long double numerator; | |
| 9 | + long double denominator; | |
| 10 | +}; | |
| 11 | + | |
| 12 | +long double pgcd ( long double m , long double n); | |
| 13 | + | |
| 14 | +int ddsFreq(int fd, int f_dds); | |
| 15 | +int setddsFreq(int fd, int f_dds, long double f0, long double fs); |
include/spi.h
| 1 | +#ifndef SPI_H | |
| 2 | +#define SPI_H | |
| 3 | + | |
| 4 | +int configureSpi(char *device); | |
| 5 | +uint16_t transfer(int fd, uint16_t valeur, int truc); | |
| 6 | +uint8_t spi_put(int fd, uint8_t valeur); | |
| 7 | +uint8_t spi_put_multiple(int fd, uint8_t *tx, uint16_t tx_size, | |
| 8 | + uint8_t *rx, uint16_t rx_size); | |
| 9 | +void setMode(int fd, uint8_t mode); | |
| 10 | +uint8_t tr2(int fd, uint8_t val); | |
| 11 | +uint8_t tr3(int fd, uint8_t *val, uint8_t *rx, uint8_t size); | |
| 12 | +int configureSpiFromFd (int fd); | |
| 13 | +#endif /*SPI_H */ |
src/ad9915.c
| 1 | +/* | |
| 2 | + SPI : initialisation du dds et communication SPI | |
| 3 | + */ | |
| 4 | +#include"ad9915.h" | |
| 5 | +#include "spi.h" | |
| 6 | +#include "ddsFreq.h" | |
| 7 | + | |
| 8 | +#define debug | |
| 9 | +//fonction reset | |
| 10 | +void Send_Reset(int f_dds) | |
| 11 | +{ | |
| 12 | + char reset='2'; | |
| 13 | + write(f_dds,&reset,sizeof(reset)); //reset | |
| 14 | + sleep(0.1); | |
| 15 | +} | |
| 16 | + | |
| 17 | +//fonction ioupdate | |
| 18 | +void Send_IO_Update(int f_dds) | |
| 19 | +{ | |
| 20 | + char update='1'; | |
| 21 | + write(f_dds,&update,sizeof(update)); //reset | |
| 22 | + sleep(0.1); | |
| 23 | +} | |
| 24 | + | |
| 25 | +//fonction write register | |
| 26 | +void write_register (int fd, unsigned char addr, unsigned char d3, unsigned char d2, unsigned char d1, unsigned char d0) | |
| 27 | +{ | |
| 28 | + unsigned char tx[5]={0}; | |
| 29 | + tx[0]=addr; | |
| 30 | + tx[1]=d3; | |
| 31 | + tx[2]=d2; | |
| 32 | + tx[3]=d1; | |
| 33 | + tx[4]=d0; | |
| 34 | + //spi_put_multiple envoie le vecteur dans cet ordre | |
| 35 | + //[tx0]-[tx1]-[tx2] -> adresse->bit poids Fort->bit poids faible | |
| 36 | + spi_put_multiple(fd,tx,5,NULL,0); | |
| 37 | +} | |
| 38 | + | |
| 39 | +//initialisation du dds | |
| 40 | +void Initialize_DDS (int fd, int f_dds) | |
| 41 | +{ | |
| 42 | + Send_Reset(f_dds); | |
| 43 | + write_register(fd,CFRAddress[0],CFR1Start[0], CFR1Start[1], CFR1Start[2], CFR1Start[3]); | |
| 44 | + Send_IO_Update (f_dds); //Send the update to set the control registers | |
| 45 | + write_register(fd,CFRAddress[1], CFR2Start[0], CFR2Start[1], CFR2Start[2], CFR2Start[3]); | |
| 46 | + Send_IO_Update (f_dds); | |
| 47 | + write_register(fd,CFRAddress[2], CFR3Start[0], CFR3Start[1], CFR3Start[2], CFR3Start[3]); | |
| 48 | + Send_IO_Update (f_dds); | |
| 49 | + write_register(fd,CFRAddress[3], CFR4Start[0], CFR4Start[1], CFR4Start[2], CFR4Start[3]); | |
| 50 | + Send_IO_Update (f_dds); | |
| 51 | + write_register(fd,USR0Address, 0xA2, 0x00, 0x08, 0x00); | |
| 52 | + Send_IO_Update (f_dds); | |
| 53 | +} | |
| 54 | + | |
| 55 | +//calibration du dac | |
| 56 | +void Calibrate_DAC (int fd, int f_dds) | |
| 57 | +{ | |
| 58 | + write_register(fd,CFRAddress[3], DACCalEnable[0], DACCalEnable[1], DACCalEnable[2], DACCalEnable[3]); | |
| 59 | + Send_IO_Update (f_dds); | |
| 60 | + write_register(fd,CFRAddress[3], CFR4Start[0], CFR4Start[1], CFR4Start[2], CFR4Start[3]); | |
| 61 | + Send_IO_Update (f_dds); | |
| 62 | +} | |
| 63 | + | |
| 64 | +void modulus_setup(int fd, int f_dds) | |
| 65 | +{ | |
| 66 | + write_register(fd,0x00,0x00, 0x01, 0x01, 0x08); //OSK enable | |
| 67 | + Send_IO_Update (f_dds); | |
| 68 | + write_register(fd,0x01,0x00, 0x89, 0x09, 0x00); //enable program modulus and digital ramp | |
| 69 | + Send_IO_Update (f_dds); | |
| 70 | +} | |
| 71 | + | |
| 72 | +void basic_setup(int fd, int f_dds,uint16_t ampWord, uint16_t phaseWord) | |
| 73 | +{ | |
| 74 | + write_register(fd,0x00,0x00, 0x01, 0x01, 0x08); //OSK enable | |
| 75 | + Send_IO_Update (f_dds); | |
| 76 | + write_register(fd,0x01,0x00, 0x89, 0x09, 0x00); //enable program modulus and digital ramp | |
| 77 | + Send_IO_Update (f_dds); | |
| 78 | + write_register(fd,0x04,0x19, 0x99, 0x99, 0x99); //ftw | |
| 79 | + Send_IO_Update (f_dds); | |
| 80 | + write_register(fd,0x05,0xC0, 0x00, 0x00, 0x00); //A | |
| 81 | + Send_IO_Update (f_dds); | |
| 82 | + write_register(fd,0x06,0x00, 0x00, 0x00, 0x05); //B | |
| 83 | + Send_IO_Update (f_dds); | |
| 84 | + //write_register(fd,0x0c, 0x0F, 0xFF, 0x00, 0x00); // amp (12b) ph(16) | |
| 85 | + write_register(fd,0x0c, (uint8_t)((ampWord>>8) & 0x0F), (uint8_t)(ampWord & 0xFF), (uint8_t)((phaseWord>>8) & 0xFF), (uint8_t)(phaseWord & 0xFF)); // amp (12b) ph(16) | |
| 86 | + Send_IO_Update (f_dds); | |
| 87 | +} | |
| 88 | + | |
| 89 | +void setFreqMM(int fd, int f_dds, unsigned int ftw, unsigned int A, unsigned int B) | |
| 90 | +{ | |
| 91 | + //uint16_t phaseWord = 0x7400; | |
| 92 | + //uint16_t ampWord = (uint16_t)strtol(argv[4],NULL,0) & 0x0FFF ; //masque en 2 | |
| 93 | + //uint16_t ampWord = 0x00000FFF; | |
| 94 | + //uint32_t phaseAmpWord = phaseWord | ampWord<<16; | |
| 95 | + | |
| 96 | + //write_register(fd,0x00,0x00, 0x01, 0x01, 0x08); //OSK enable | |
| 97 | + //Send_IO_Update(f_dds); | |
| 98 | + //write_register(fd,0x01,0x00, 0x89, 0x09, 0x00); //enable program modulus and digital ramp | |
| 99 | + //Send_IO_Update(f_dds); | |
| 100 | + write_register(fd,0x04,ftw>>24&0xFF, ftw>>16&0xFF, ftw>>8&0xFF, ftw&0xFF); //ftw | |
| 101 | + Send_IO_Update(f_dds); | |
| 102 | + write_register(fd,0x05,A>>24&0xFF,A>>16&0xFF, A>>8&0xFF, A&0xFF); //A | |
| 103 | + Send_IO_Update(f_dds); | |
| 104 | + write_register(fd,0x06,B>>24&0xFF,B>>16&0xFF, B>>8&0xFF, B&0xFF); //B | |
| 105 | + Send_IO_Update(f_dds); | |
| 106 | + // write_register(fd,0x0c, phaseAmpWord>>24&0xFF, phaseAmpWord>>16&0xFF,phaseAmpWord>>8&0xFF,phaseAmpWord&0xFF); // amp (12b) ph(16) | |
| 107 | + //Send_IO_Update(f_dds); | |
| 108 | +} | |
| 109 | + | |
| 110 | +void setAmpPhaseWord(int fd, int f_dds,unsigned int phaseAmpWord) | |
| 111 | +{ | |
| 112 | + write_register(fd,0x0c, phaseAmpWord>>24&0xFF, phaseAmpWord>>16&0xFF,phaseAmpWord>>8&0xFF,phaseAmpWord&0xFF); // amp (12b) ph(16) | |
| 113 | + Send_IO_Update(f_dds); | |
| 114 | +} | |
| 115 | + | |
| 116 | + | |
| 117 | +int openAndSetDdsFreq( char * device, char * gpio_update, double f_clk, double f_out, uint16_t ampWord, uint16_t phaseWord) | |
| 118 | +{ | |
| 119 | + #ifdef debug | |
| 120 | + printf("device=%s\tgpio_update=%s\tf_clk=%e\tf_out=%e\tampWord=%d\tphaseWord=%d\n\n",device,gpio_update,f_clk,f_out,ampWord,phaseWord); | |
| 121 | + #else | |
| 122 | + printf("device=%s\tgpio_update=%s\tf_clk=%e\tf_out=%e\tampWord=%d\tphaseWord=%d\n\n",device,gpio_update,f_clk,f_out,ampWord,phaseWord); | |
| 123 | + int fd=configureSpi(device); //ex #define FILENAME2 "/dev/spidev0.0" | |
| 124 | + printf("fd(funct)=%d\n",fd); | |
| 125 | + setMode(fd,SPI_MODE_0); | |
| 126 | + if (fd <= 0){ | |
| 127 | + printf("ERREUR : ouverture pรฉriphรฉrique SPI %s\n",device); | |
| 128 | + return EXIT_FAILURE; | |
| 129 | + } | |
| 130 | + int f_dds=open(gpio_update,O_RDWR); //ex #define UPDATE2 "/sys/dds/gpio24/updateOn" | |
| 131 | + printf("f_dds(funct)=%d\n",f_dds); | |
| 132 | + if (f_dds <= 0){ | |
| 133 | + printf("ERREUR : ouverture ");printf(gpio_update);printf("\n"); | |
| 134 | + printf("Chargez le module ddsIOupdateX\n"); | |
| 135 | + return EXIT_FAILURE; | |
| 136 | + } | |
| 137 | + setddsFreq(fd,f_dds,f_out,f_clk); | |
| 138 | + //debug | |
| 139 | + phaseWord = 0x0000; | |
| 140 | + ampWord=0x0FFF; | |
| 141 | + uint32_t phaseAmpWord = phaseWord | ampWord<<16; | |
| 142 | + setAmpPhaseWord(fd, f_dds, phaseAmpWord); | |
| 143 | + #endif | |
| 144 | + return EXIT_SUCCESS; | |
| 145 | +} | |
| 146 | + | |
| 147 | +int setDdsFreqFull ( int fd, int f_dds, double f_clk, double f_out, uint16_t ampWord, uint16_t phaseWord) | |
| 148 | +{ | |
| 149 | + setddsFreq(fd,f_dds,f_out,f_clk); | |
| 150 | + #ifdef debug | |
| 151 | + phaseWord = 0x0000; | |
| 152 | + ampWord=0x0FFF; | |
| 153 | + #endif | |
| 154 | + uint32_t phaseAmpWord = phaseWord | ampWord<<16; | |
| 155 | + setAmpPhaseWord(fd, f_dds, phaseAmpWord); | |
| 156 | + | |
| 157 | + return EXIT_SUCCESS; | |
| 158 | +} | |
| 159 | + | |
| 160 | +int receiveParameterFromPythonServer(char * device, double f_clk, double f_out){ | |
| 161 | + | |
| 162 | + printf("receiveParameterFromPythonServer::device=%s\tf_clk=%e\tf_out=%e\n",device,f_clk,f_out); | |
| 163 | + return 0; | |
| 164 | +} |
src/ddsFreq.c
| 1 | +#include <stdlib.h> | |
| 2 | +#include <stdio.h> | |
| 3 | +#include <unistd.h> | |
| 4 | +#include <math.h> | |
| 5 | +#include "ddsFreq.h" | |
| 6 | +#include "ad9915.h" | |
| 7 | + | |
| 8 | +//#define debug | |
| 9 | +long double pgcd ( long double m , long double n) | |
| 10 | +{ | |
| 11 | + if (fmod(m,n) ==0) | |
| 12 | + return n; | |
| 13 | + return pgcd(n,fmod(m,n)); | |
| 14 | +} | |
| 15 | + | |
| 16 | +int setddsFreq(int fd, int f_dds, long double f0, long double fs) | |
| 17 | +{ | |
| 18 | + | |
| 19 | + #ifdef debug | |
| 20 | + printf("f0=%Le\tfs=%Le\n",f0,fs); | |
| 21 | + #endif | |
| 22 | + | |
| 23 | + if (fs<0 || f0<0) return EXIT_FAILURE; | |
| 24 | + | |
| 25 | + struct frac f1; | |
| 26 | + | |
| 27 | + f1.numerator = f0; | |
| 28 | + f1.denominator = fs; | |
| 29 | + | |
| 30 | + long double d1 = pgcd (f1.numerator , f1.denominator ); | |
| 31 | + //printf(" d1 = %24.16Lf\n",d1); | |
| 32 | + | |
| 33 | + long double M = f0 / d1 ; | |
| 34 | + long double N = fs / d1 ; | |
| 35 | + //printf(" M = f0 / d1 = %24.16Lf\n",M); | |
| 36 | + //printf(" N = fs / d1 = %24.16Lf\n",N); | |
| 37 | + | |
| 38 | + | |
| 39 | + long double ftw = M * scalbn(1.0,32); | |
| 40 | + ftw /= N; | |
| 41 | + //printf("ftw = %24.16Lf\n",ftw); | |
| 42 | + | |
| 43 | + | |
| 44 | + //printf("X=floor(ftw) = %24.16Lf\n",(long double)floor(ftw)); | |
| 45 | + | |
| 46 | + long double Y = M * scalbn(1.0,32); | |
| 47 | + Y -= N * floor(ftw); | |
| 48 | + //printf("Y=M*2**32-X*N = %24.16Lf\n",Y); | |
| 49 | + | |
| 50 | + long double d2 = pgcd (Y,N); | |
| 51 | + //printf(" d2 = %24.16Lf\n",d2); | |
| 52 | + | |
| 53 | + long double A = Y / d2; | |
| 54 | + long double B = N / d2; | |
| 55 | + //printf("A = Y/d2 = %24.16Lf\n",A); | |
| 56 | + //printf("B = N/d2 = %24.16Lf\n",B); | |
| 57 | + | |
| 58 | + //printf("f0 = (M/N) * fclk= %24.32Lf\n",fs*M/N); | |
| 59 | + //printf("f0 = (X+A/B)2**32= %24.32Lf\n",fs*(floor(ftw)+A/B)/scalbn(1.0,32)); | |
| 60 | + | |
| 61 | +#ifdef debug | |
| 62 | +printf("\n so finally the programmed registers are :\n" | |
| 63 | + "ftw= 0x%08x A= 0x%08x B= 0x%08x\n" | |
| 64 | + "",(unsigned int)ftw,(unsigned int)A,(unsigned int)B); | |
| 65 | +printf("uint ftw = %d\n",(unsigned int)ftw); | |
| 66 | + | |
| 67 | +printf("\n 0x%08x 0x%08x 0x%08x \n\n",(unsigned int)ftw,(unsigned int)A,(unsigned int)B); | |
| 68 | +//setFreqMM(fd,f_dds,(unsigned int)ftw, (unsigned int)A, (unsigned int)B); | |
| 69 | +#endif | |
| 70 | +setFreqMM(fd,f_dds,(unsigned int)ftw, 2*(unsigned int)B, 2*(unsigned int)A); //??why *2?? | |
| 71 | + return EXIT_SUCCESS; | |
| 72 | +} | |
| 73 | +int ddsFreq(int fd, int f_dds) | |
| 74 | +{ | |
| 75 | + //checkSize(); | |
| 76 | + long double f0,fs; | |
| 77 | + //printf("long = %lu\n",sizeof (long)); | |
| 78 | + //printf("float = %lu\n",sizeof (float)); | |
| 79 | + //printf("double = %lu\n",sizeof (double)); | |
| 80 | + //printf("long double = %lu\n",sizeof (long double)); | |
| 81 | + | |
| 82 | + printf("\nDesired output Frequency (MHz) : "); | |
| 83 | + scanf("%Lf",&f0); | |
| 84 | + printf("DDS frequency Clock (MHz) : "); | |
| 85 | + scanf("%Lf",&fs); | |
| 86 | + | |
| 87 | + //long double f0=atof(argv[1]); //desired output freq | |
| 88 | + //long double fs=atof(argv[2]); //dds_clk | |
| 89 | + //int toto = (int)strtol(argv[3],NULL,0); | |
| 90 | + //printf("toto=%d\t%x\n",toto,toto); | |
| 91 | + | |
| 92 | + if (fs<0 || f0<0) return EXIT_FAILURE; | |
| 93 | + | |
| 94 | + struct frac f1; | |
| 95 | + | |
| 96 | + f1.numerator = f0; | |
| 97 | + f1.denominator = fs; | |
| 98 | + | |
| 99 | + long double d1 = pgcd (f1.numerator , f1.denominator ); | |
| 100 | + printf(" d1 = %24.16Lf\n",d1); | |
| 101 | + | |
| 102 | + long double M = f0 / d1 ; | |
| 103 | + long double N = fs / d1 ; | |
| 104 | + printf(" M = f0 / d1 = %24.16Lf\n",M); | |
| 105 | + printf(" N = fs / d1 = %24.16Lf\n",N); | |
| 106 | + | |
| 107 | + | |
| 108 | + long double ftw = M * scalbn(1.0,32); | |
| 109 | + ftw /= N; | |
| 110 | + printf("ftw = %24.16Lf\n",ftw); | |
| 111 | + | |
| 112 | + | |
| 113 | + printf("X=floor(ftw) = %24.16Lf\n",(long double)floor(ftw)); | |
| 114 | + | |
| 115 | + long double Y = M * scalbn(1.0,32); | |
| 116 | + Y -= N * floor(ftw); | |
| 117 | + printf("Y=M*2**32-X*N = %24.16Lf\n",Y); | |
| 118 | + | |
| 119 | + long double d2 = pgcd (Y,N); | |
| 120 | + printf(" d2 = %24.16Lf\n",d2); | |
| 121 | + | |
| 122 | + long double A = Y / d2; | |
| 123 | + long double B = N / d2; | |
| 124 | + printf("A = Y/d2 = %24.16Lf\n",A); | |
| 125 | + printf("B = N/d2 = %24.16Lf\n",B); | |
| 126 | + | |
| 127 | + printf("f0 = (M/N) * fclk= %24.32Lf\n",fs*M/N); | |
| 128 | + printf("f0 = (X+A/B)2**32= %24.32Lf\n",fs*(floor(ftw)+A/B)/scalbn(1.0,32)); | |
| 129 | + | |
| 130 | +printf("\n so finally the programmed registers are :\n" | |
| 131 | + "ftw= 0x%08x A= 0x%08x B= 0x%08x\n" | |
| 132 | + "",(unsigned int)ftw,(unsigned int)A,(unsigned int)B); | |
| 133 | +//printf("uint ftw = %d\n",(unsigned int)ftw); | |
| 134 | + | |
| 135 | +printf("\n 0x%08x 0x%08x 0x%08x \n\n",(unsigned int)ftw,(unsigned int)A,(unsigned int)B); | |
| 136 | +//setFreqMM(fd,f_dds,(unsigned int)ftw, (unsigned int)A, (unsigned int)B); | |
| 137 | +setFreqMM(fd,f_dds,(unsigned int)ftw, 2*(unsigned int)B, 2*(unsigned int)A); | |
| 138 | + return EXIT_SUCCESS; | |
| 139 | +} |
src/spi.c
| 1 | +#include <stdint.h> | |
| 2 | +#include <unistd.h> | |
| 3 | +#include <stdio.h> | |
| 4 | +#include <stdlib.h> | |
| 5 | +#include <getopt.h> | |
| 6 | +#include <fcntl.h> | |
| 7 | +#include <sys/ioctl.h> | |
| 8 | +#include <linux/types.h> | |
| 9 | +#include <linux/spi/spidev.h> | |
| 10 | +/* memory management */ | |
| 11 | +#include <sys/mman.h> | |
| 12 | +#include "spi.h" | |
| 13 | +#include <string.h> | |
| 14 | + | |
| 15 | +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | |
| 16 | + | |
| 17 | +#undef DEBUG | |
| 18 | +//#define DEBUG | |
| 19 | +static uint8_t bits = 8; | |
| 20 | +//static uint32_t speed = 15000000; // 9600; | |
| 21 | +//static uint32_t speed = 20000000; // 9600; | |
| 22 | +static uint32_t speed = 10000000; | |
| 23 | +//static uint32_t speed = 100000; // 9600; | |
| 24 | +//static uint16_t delay; | |
| 25 | +static void | |
| 26 | +pabort (const char *s) | |
| 27 | +{ | |
| 28 | + perror (s); | |
| 29 | + abort (); | |
| 30 | +} | |
| 31 | + | |
| 32 | +uint8_t | |
| 33 | +spi_put_multiple (int fd, uint8_t * tx, uint16_t tx_size, | |
| 34 | + uint8_t * rx, uint16_t rx_size) | |
| 35 | +{ | |
| 36 | + int ret; | |
| 37 | + int nb = 2; | |
| 38 | + if (rx_size == 0 || tx_size == 0) | |
| 39 | + nb = 1; | |
| 40 | + struct spi_ioc_transfer xfer[nb]; | |
| 41 | + nb = 0; | |
| 42 | + memset (xfer, 0, sizeof (xfer)); | |
| 43 | + if (tx_size > 0) | |
| 44 | + { | |
| 45 | + xfer[nb].tx_buf = (unsigned long) tx; | |
| 46 | + xfer[nb].len = tx_size; | |
| 47 | + nb++; | |
| 48 | + } | |
| 49 | + if (rx_size > 0) | |
| 50 | + { | |
| 51 | + xfer[nb].rx_buf = (unsigned long) rx; | |
| 52 | + xfer[nb].len = rx_size; | |
| 53 | + nb++; | |
| 54 | + } | |
| 55 | + ret = ioctl (fd, SPI_IOC_MESSAGE (nb), xfer); | |
| 56 | + return ret; | |
| 57 | +} | |
| 58 | + | |
| 59 | +uint8_t | |
| 60 | +tr3 (int fd, uint8_t * val, uint8_t * rx, uint8_t size) | |
| 61 | +{ | |
| 62 | + int ret; | |
| 63 | + | |
| 64 | + struct spi_ioc_transfer xfer[2]; | |
| 65 | + memset (xfer, 0, sizeof (xfer)); | |
| 66 | + | |
| 67 | + xfer[0].tx_buf = (unsigned long) val; | |
| 68 | + xfer[0].len = size; | |
| 69 | + xfer[1].rx_buf = (unsigned long) rx; | |
| 70 | + xfer[1].len = size; | |
| 71 | + | |
| 72 | + ret = ioctl (fd, SPI_IOC_MESSAGE (2), xfer); | |
| 73 | + if (ret < 1) | |
| 74 | + { | |
| 75 | + pabort ("can't send spi message"); | |
| 76 | + } | |
| 77 | + return ret; | |
| 78 | +} | |
| 79 | + | |
| 80 | +void | |
| 81 | +setMode (int fd, uint8_t mode) | |
| 82 | +{ | |
| 83 | + if (ioctl (fd, SPI_IOC_WR_MODE, &mode) < 0) | |
| 84 | + pabort ("can't set mode"); | |
| 85 | + if (ioctl (fd, SPI_IOC_RD_MODE, &mode) < 0) | |
| 86 | + pabort ("can't get mode"); | |
| 87 | +} | |
| 88 | + | |
| 89 | +uint8_t | |
| 90 | +spi_put (int fd, uint8_t valeur) | |
| 91 | +{ | |
| 92 | + int ret; | |
| 93 | + uint8_t rx_buf[1], tx_buf[1]; | |
| 94 | + tx_buf[0] = valeur; | |
| 95 | + struct spi_ioc_transfer xfer[2]; | |
| 96 | + memset (xfer, 0, sizeof (xfer)); | |
| 97 | + | |
| 98 | + xfer[0].tx_buf = (unsigned long) tx_buf; | |
| 99 | + xfer[0].rx_buf = (unsigned long) rx_buf; | |
| 100 | + xfer[0].len = 1; | |
| 101 | + ret = ioctl (fd, SPI_IOC_MESSAGE (1), xfer); | |
| 102 | + if (ret < 1) | |
| 103 | + { | |
| 104 | + pabort ("can't send spi message"); | |
| 105 | + } | |
| 106 | + return rx_buf[0]; | |
| 107 | +} | |
| 108 | + | |
| 109 | +int | |
| 110 | +configureSpi (char *device) | |
| 111 | +{ | |
| 112 | + printf("device(configureSpi)=%s\n",device); | |
| 113 | + int fd = open (device, O_RDWR); | |
| 114 | + if (fd < 0) | |
| 115 | + pabort ("can't open device"); | |
| 116 | + | |
| 117 | + setMode (fd, 0); | |
| 118 | + /* bits per word */ | |
| 119 | + if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) | |
| 120 | + pabort ("can't set bits per word"); | |
| 121 | + if (ioctl (fd, SPI_IOC_RD_BITS_PER_WORD, &bits) == -1) | |
| 122 | + pabort ("can't get bits per word"); | |
| 123 | + | |
| 124 | + /* max speed hz */ | |
| 125 | + if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1) | |
| 126 | + pabort ("can't set max speed hz"); | |
| 127 | + | |
| 128 | + if (ioctl (fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1) | |
| 129 | + pabort ("can't get max speed hz"); | |
| 130 | +//#ifdef DEBUG | |
| 131 | + //printf("spi mode: %d\n", mode); | |
| 132 | + //printf ("bits per word: %d\r\n", bits); | |
| 133 | + //printf ("max speed: %lu Hz (%lu kHz)\r\n", | |
| 134 | +// (unsigned long) speed, ((unsigned long) speed) / 1000); | |
| 135 | +//#endif /* DEBUG */ | |
| 136 | + return fd; | |
| 137 | +} | |
| 138 | + | |
| 139 | +int configureSpiFromFd (int fd) | |
| 140 | +{ | |
| 141 | + setMode (fd, 0); | |
| 142 | + /* bits per word */ | |
| 143 | + if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) | |
| 144 | + pabort ("can't set bits per word"); | |
| 145 | + if (ioctl (fd, SPI_IOC_RD_BITS_PER_WORD, &bits) == -1) | |
| 146 | + pabort ("can't get bits per word"); | |
| 147 | + | |
| 148 | + /* max speed hz */ | |
| 149 | + if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1) | |
| 150 | + pabort ("can't set max speed hz"); | |
| 151 | + | |
| 152 | + if (ioctl (fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1) | |
| 153 | + pabort ("can't get max speed hz"); | |
| 154 | +#ifdef DEBUG | |
| 155 | +//printf("spi mode: %d\n", mode); | |
| 156 | +printf ("bits per word: %d\r\n", bits); | |
| 157 | +printf ("max speed: %lu Hz (%lu kHz)\r\n", | |
| 158 | + (unsigned long) speed, ((unsigned long) speed) / 1000); | |
| 159 | +#endif /* DEBUG */ | |
| 160 | + return EXIT_SUCCESS; | |
| 161 | +} |