]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control-pxmc.git/blob - src/app/rpi-pmsm-test1/rpi_spi.c
5e93cc1f9af72f46ec632a86c42f05b9095d212b
[fpga/rpi-motor-control-pxmc.git] / src / app / rpi-pmsm-test1 / rpi_spi.c
1 /*
2   Communication with Raspberry Pi equipped by 3-phase
3   motor driver and RPI-MI-1 FPGA board designed
4   by Petr Porazil for PiKRON company.
5   The VHDL design by Martin Prudek.
6
7   (C) 2015 by Martin Prudek prudemar@fel.cvut.cz
8   (C) 2015 by Pavel Pisa pisa@cmp.felk.cvut.cz
9  */
10
11 #include <stdint.h>
12 #include <unistd.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <getopt.h>
17 #include <fcntl.h>
18 #include <sys/ioctl.h>
19 #include <linux/types.h>
20 #include <linux/spi/spidev.h>
21
22 #include "pxmc_spimc.h"
23
24 #define SPIMC_INDEX_BITS 12
25 #define SPIMC_INDEX_MASK ((1 << SPIMC_INDEX_BITS) - 1)
26
27 static uint8_t spimc_mode = 0;
28 static uint8_t spimc_bits = 8;
29 static uint32_t spimc_speed = 500000;
30 static uint16_t spimc_delay = 0;
31
32 static void pabort(const char *s)
33 {
34         perror(s);
35         abort();
36 }
37
38 int spimc_transfer(spimc_state_t *spimcst)
39 {
40         uint8_t *tx = spimcst->tx_buf;
41         uint8_t *rx = spimcst->rx_buf;
42         int ret;
43         uint32_t pwm1, pwm2, pwm3;
44         uint32_t idx;
45         int32_t  idxdiff;
46
47         memset(tx, 0, SPIMC_TRANSFER_SIZE);
48         memset(rx, 0, SPIMC_TRANSFER_SIZE);
49
50         /*Data format:
51          * rx[0] - bity 127 downto 120 the first income bit..127
52          * rx[1] - bity 119 downto 112
53          * rx[2] - bity 111 downto 104
54          * rx[3] - bity 103 downto 96
55          * tx[4] - bity 95 downto 88
56          * tx[5] - bity 87 downto 80
57          * tx[6] - bity 79 downto 72
58          * tx[7] - bity 71 downto 64
59          * tx[8] - bity 63 downto 56
60          * tx[9] - bity 55 downto 48
61          * tx[10] - bity 47 downto 40
62          * tx[11] - bity 39 downto 32
63          * tx[12] - bity 31 downto 24
64          * tx[13] - bity 23 downto 16
65          * tx[14] - bity 15 downto 8
66          * tx[15] - bity 7 downto 0
67          *
68          * bit 127 - ADC reset
69          * bit 126 - enable PWM1
70          * bit 125 - enable PWM2
71          * bit 124 - enable PWM3
72          * bit 123 - shutdown1
73          * bit 122 - shutdown2
74          * bit 121 - shutdown3
75          *      .
76          * bits 47 .. 32 - match PWM1
77          * bits 31 .. 16 - match PWM2
78          * bits 15 .. 0  - match PWM3
79          */
80
81         pwm1 = spimcst->pwm[0];
82         pwm2 = spimcst->pwm[1];
83         pwm3 = spimcst->pwm[2];
84
85         tx[0] = 0;
86         if (pwm1 & SPIMC_PWM_ENABLE)
87           tx[0] |= 1 << 6;
88         if (pwm1 & SPIMC_PWM_SHUTDOWN)
89           tx[0] |= 1 << 3;
90         if (pwm2 & SPIMC_PWM_ENABLE)
91           tx[0] |= 1 << 5;
92         if (pwm2 & SPIMC_PWM_SHUTDOWN)
93           tx[0] |= 1 << 2;
94         if (pwm3 & SPIMC_PWM_ENABLE)
95           tx[0] |= 1 << 4;
96         if (pwm3 & SPIMC_PWM_SHUTDOWN)
97           tx[0] |= 1 << 1;
98
99         pwm1 &= SPIMC_PWM_VALUE_m;
100         pwm2 &= SPIMC_PWM_VALUE_m;
101         pwm3 &= SPIMC_PWM_VALUE_m;
102
103         /* keep the cap*/
104         if (pwm1 > 2047) pwm1 = 2047;
105         if (pwm2 > 2047) pwm2 = 2047;
106         if (pwm3 > 2047) pwm3 = 2047;
107
108         /*pwm1*/
109         tx[10] = pwm1 >> 8;   /*MSB*/
110         tx[11] = pwm1 & 0xff; /*LSB*/
111
112         /*pwm2*/
113         tx[12] = pwm2 >> 8;   /*MSB*/
114         tx[13] = pwm2 & 0xff; /*LSB*/
115
116         /*pwm3*/
117         tx[14] = pwm3 >> 8;   /*MSB*/
118         tx[15] = pwm3 & 0xff; /*LSB*/
119
120         struct spi_ioc_transfer tr = {
121                 .tx_buf = (uintptr_t)tx,
122                 .rx_buf = (uintptr_t)rx,
123                 .len = SPIMC_TRANSFER_SIZE,
124                 .delay_usecs = spimc_delay,
125                 .speed_hz = spimc_speed,
126                 .bits_per_word = spimc_bits,
127         };
128
129         ret = ioctl(spimcst->spi_fd, SPI_IOC_MESSAGE(1), &tr);
130         if (ret < 1)
131                 return -1;
132
133         /*prichozi data:
134          * rx[0] - bity 127 downto 120 the first income bit..127
135          * rx[1] - bity 119 downto 112
136          * rx[2] - bity 111 downto 104
137          * rx[3] - bity 103 downto 96
138          * rx[4] - bity 95 downto 88
139          * rx[5] - bity 87 downto 80
140          * rx[6] - bity 79 downto 72
141          * rx[7] - bity 71 downto 64
142          * rx[8] - bity 63 downto 56
143          * rx[9] - bity 55 downto 48
144          * rx[10] - bity 47 downto 40
145          * rx[11] - bity 39 downto 32
146          * rx[12] - bity 31 downto 24
147          * rx[13] - bity 23 downto 16
148          * rx[14] - bity 15 downto 8
149          * rx[15] - bity 7 downto 0     the last income bit..0
150          */
151
152         /* position from IRC counter */
153         spimcst->act_pos = ((uint32_t)rx[0] << 24) |
154                            ((uint32_t)rx[1] << 16) |
155                            ((uint32_t)rx[2] << 8) |
156                            ((uint32_t)rx[3] << 0);
157
158         /*halove sondy
159          * hal1 - bit95
160          * hal2 - bit94
161          * hal3 - bit93
162          */
163         spimcst->hal_sensors = ((0x80 & rx[4]) >> 7) |
164                                ((0x40 & rx[4]) >> 5) |
165                                ((0x20 & rx[4]) >> 3);
166
167         /* index position
168          * bits 92 downto 81
169          *      92..88 in rx[4] last 5 bits (from left)
170          *      87..81 in rx[5] first 7 bits (from left)
171          */
172         idx = 0x1F & rx[4];
173         idx <<= 8;
174         idx |= 0xFE & rx[5];
175         idx >>= 1;
176
177         if ((idx ^ spimcst->index_pos) & SPIMC_INDEX_MASK) {
178                 idxdiff = (idx - spimcst->act_pos +
179                            (1 << (SPIMC_INDEX_BITS - 1))) & SPIMC_INDEX_MASK;
180                 idxdiff -= 1 << (SPIMC_INDEX_BITS - 1);
181                 idx = spimcst->act_pos + idxdiff;
182                 spimcst->index_pos = idx;
183                 spimcst->index_occur += 1;
184         }
185
186         /* current measurments count
187          * bits 80 downto 72
188          * bit 80 in rx[5]
189          * bits 79..72 in rx[6]
190          */
191
192         spimcst->curadc_sqn = 0x01 & rx[5];
193         spimcst->curadc_sqn <<= 8;
194         spimcst->curadc_sqn |= rx[6];
195
196
197         /** currents
198          * ch2 - bits 71 downto 48
199          *      71..64 in rx[7] - all byte
200          *      63..56 in rx[8] - all byte
201          *      55..48 in rx[9] - all byte
202          * ch0 - bits 47 downto 24
203          *      47..40 in rx[10] - all byte
204          *      39..32 in rx[11] - all byte
205          *      31..24 in rx[12] - all byte
206          * ch1 - bits 23 downto 0
207          *      23..16 in rx[13] - all byte
208          *      15..8 in rx[14] - all byte
209          *      7..0 in rx[15] - all byte
210          */
211
212         spimcst->curadc_cumsum[2] = rx[7];
213         spimcst->curadc_cumsum[2] <<= 8;
214         spimcst->curadc_cumsum[2] |= rx[8];
215         spimcst->curadc_cumsum[2] <<= 8;
216         spimcst->curadc_cumsum[2] |= rx[9];
217
218         spimcst->curadc_cumsum[0] = rx[10];
219         spimcst->curadc_cumsum[0] <<= 8;
220         spimcst->curadc_cumsum[0] |= rx[11];
221         spimcst->curadc_cumsum[0] <<= 8;
222         spimcst->curadc_cumsum[0] |=rx [12];
223
224         spimcst->curadc_cumsum[1] = rx[13];
225         spimcst->curadc_cumsum[1] <<= 8;
226         spimcst->curadc_cumsum[1] |= rx[14];
227         spimcst->curadc_cumsum[1] <<= 8;
228         spimcst->curadc_cumsum[1] |= rx[15];
229
230         return 0;
231 }
232
233 int spimc_init(spimc_state_t *spimcst)
234 {
235         int ret = 0;
236         int fd;
237
238         spimcst->spi_fd = -1;
239
240         fd = open(spimcst->spi_dev, O_RDWR);
241         if (fd < 0) {
242                 pabort("can't open device");
243         }
244         printf("device open\n");
245         /*
246          * spi spimc_mode
247          */
248         ret = ioctl(fd, SPI_IOC_WR_MODE, &spimc_mode);
249         if (ret == -1)
250                 pabort("can't set spi mode");
251
252         ret = ioctl(fd, SPI_IOC_RD_MODE, &spimc_mode);
253         if (ret == -1)
254                 pabort("can't get spi mode");
255
256         /*
257          * bits per word
258          */
259         ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spimc_bits);
260         if (ret == -1)
261                 pabort("can't set bits per word");
262
263         ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &spimc_bits);
264         if (ret == -1)
265                 pabort("can't get bits per word");
266
267         /*
268          * max spimc_speed hz
269          */
270         ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spimc_speed);
271         if (ret == -1)
272                 pabort("can't set max speed hz");
273
274         ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &spimc_speed);
275         if (ret == -1)
276                 pabort("can't get max speed hz");
277
278         printf("spi spimc_mode: %d\n", spimc_mode);
279         printf("bits per word: %d\n", spimc_bits);
280         printf("delay: %d\n", spimc_delay);
281         printf("max spimc_speed: %d Hz (%d KHz)\n", spimc_speed, spimc_speed/1000);
282
283         spimcst->spi_fd = fd;
284
285         return ret;
286 }