]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/din.c
Implemented use variable threshold in RPP DIN API.
[pes-rpp/rpp-lib.git] / rpp / src / drv / din.c
1 /*
2  * din.c
3  *
4  *  Created on: 17.12.2012
5  *      Author: Michal Horn
6  *
7  *  This file contains functions to control DIN
8  *  Voltage on each pin can be set
9  *  switch to ground or to battery on programable pins can be set
10  *  interrupts on each pins can be disabled and enabled
11  */
12
13 //#include "drv_din.h"
14 #include "drv/drv.h"
15
16 /** Prepared command */
17 uint32_t din_spi_cmd = DIN_SPICMD_INIT_VAL;
18 /** Shadow variable used during sending */
19 uint32_t din_spi_cmd_sh = DIN_SPICMD_INIT_VAL;
20 /** Stored response from SPI */
21 uint32_t din_spi_resp = 0;
22 /** Prepared command for change status on SP pins */
23 uint32_t pin_st_p_cmd;
24 /** Prepared command for change status on SG pins */
25 uint32_t pin_st_g_cmd;
26 /** Prepared command for disabling interrupt on SP pins */
27 uint32_t pin_int_p_cmd;
28 /** Prepared command for disabling interrupt on SG pins */
29 uint32_t pin_int_g_cmd;
30
31 /** Signal for state cmd transfer */
32 uint8_t transfer_state_cmd = 0;
33 /** Signal for interrupt cmd trasfer */
34 uint8_t transfer_interrupt_cmd = 0;
35
36 /** Indexes of bits in status commands assigned to pins */
37 static const uint32_t din_set_pin_st_i[]  = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7};
38 /** Indexes of bits in switch-to commands assigned to pins */
39 static const uint32_t din_set_pin_pr_i[]  = {0, 1, 2, 3, 4, 5, 6, 7};
40 /** Indexes of bits in response assigned to pins */
41 static const uint32_t din_get_pin_val_i[]  = {14, 15, 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7};
42
43 /*
44  * Get DIN pin value.
45  * @param pin index of pin according the scheme (0-15)
46  * @return value on pin or -1 if error
47  */
48 int din_get_pin_val(uint32_t pin) {
49     if (pin > 15) return -1;
50     return ((din_spi_resp & (1 << din_get_pin_val_i[pin])) > 0);
51 }
52
53 const static uint32_t dsc_pin_map[] = {
54     PIN_DSC_DIN8,
55     PIN_DSC_DIN9,
56     PIN_DSC_DIN10,
57     PIN_DSC_DIN11,
58     PIN_DSC_DIN12,
59     PIN_DSC_DIN13,
60     PIN_DSC_DIN14,
61     PIN_DSC_DIN15
62 };
63
64 int8_t drv_din_get_varthr(uint8_t pin) {
65
66     // Check range
67     if((pin < 8) || (pin > 15)) {
68         return FAILURE;
69     }
70
71     return hal_gpio_pin_get_value(dsc_pin_map[pin - 8]);
72 }
73
74 /**
75  * Set programmable pin DIN_SP according bits in argument as switch-to-battery (1) or switch-to-ground(0)
76  * @param word  8-bit array representing switch-to state
77  */
78 void din_set_pr(uint8_t word) {
79     int i;
80     uint8_t val;
81     din_spi_cmd = 1 << 16;  // Set command
82
83     for (i = 0; i < 8; i++,word >>= 1) {
84         val = word&0x1;
85         if (val == 1) {
86             din_spi_cmd |= 1 << din_set_pin_pr_i[i];
87         }
88         else if (val == 0) {
89             din_spi_cmd &= ~(1 << din_set_pin_pr_i[i]);
90         }
91     }
92 }
93
94 /**
95  * Set DIN pins to be tri-state (1) or Active (0)
96  * @param sp_state 16-bit variable representing state of SP pins. (0 - active, 1 - tri-state).
97  * @param sg_state 16-bit variable representing state of SG pins. (0 - active, 1 - tri-state).
98  */
99 void din_set_stat(uint16_t sp_state, uint16_t sg_state) {
100     int i;
101     uint16_t val;
102     uint32_t state = (sp_state&0xFF)|((sg_state&0xFF)<<8);
103     uint32_t* pin_cmd_ptr = NULL;
104     pin_st_p_cmd = 0x9 << 16;       // Set command for SP pins
105     pin_st_g_cmd = 0xA << 16;       // Set command for SG pins
106     for (i = 0; i < 16; i++,state >>= 1) {
107         val = state&0x1;
108         if (i < 8) {    // First 8 pins SP0 - SP7
109             pin_cmd_ptr = &pin_st_p_cmd;
110         }
111         else { // Another 8 pins SG0 - SG7
112             pin_cmd_ptr = &pin_st_g_cmd;
113         }
114
115         if (val) {
116             *pin_cmd_ptr |= 1 << din_set_pin_st_i[i];
117         }
118         else {
119             *pin_cmd_ptr &= ~(1 << din_set_pin_st_i[i]);
120         }
121     }
122     transfer_state_cmd = 1; // Enable transfer of two commands at once
123 }
124
125 /**
126  * Enable/disable interrupts for DIN pins as well as acting pins as wake-up
127  * @param sp_int_enable 16-bit variable representing interrupt enablers for SP pins (0 - disable wake-up and interrupt, 1 - enable interrupt).
128  * @param sg_int_enable 16-bit variable representing interrupt enablers for SG pins (0 - disable wake-up and interrupt, 1 - enable interrupt).
129  */
130 void din_set_int(uint16_t sp_int_enable, uint16_t sg_int_enable) {
131     int i;
132     uint16_t val;
133     uint32_t int_enable = (sp_int_enable&0xFF)|((sg_int_enable&0xFF)<<8);
134     uint32_t* pin_cmd_ptr = NULL;
135     pin_int_p_cmd = 0x2 << 16;      // Set command for SP pins
136     pin_int_g_cmd = 0x3 << 16;      // Set command for SG pins
137     for (i = 0; i < 16; i++,int_enable >>= 1) {
138         val = int_enable&0x1;
139         if (i < 8) {    // First 8 pins SP0 - SP7
140             pin_cmd_ptr = &pin_int_p_cmd;
141         }
142         else { // Another 8 pins SG0 - SG7
143             pin_cmd_ptr = &pin_int_g_cmd;
144         }
145
146         if (val) {
147             *pin_cmd_ptr |= 1 << din_set_pin_st_i[i];
148         }
149         else {
150             *pin_cmd_ptr &= ~(1 << din_set_pin_st_i[i]);
151         }
152     }
153     transfer_interrupt_cmd = 1; // Enable transfer of two commands at once
154 }
155
156 /**
157  * Prepare reset command to be sent through spi
158  */
159 void din_reset() {
160     din_spi_cmd = 0x7F0000;
161 }
162
163 /**
164  * Prepare switch status command to be sent through spi
165  */
166 void din_switch_st() {
167     din_spi_cmd = 0x0;
168 }
169
170 /**
171  * Get values of all DIN pins in form of 16-bit word DIN15,...,DIN0
172  * @return values of all pins DIN0 - DIN15
173  */
174 uint16_t din_get_val_word() {
175     uint16_t word = 0;
176     int i;
177     for (i = 0; i < 16; i++) {
178         word |= din_get_pin_val(i) << i;
179     }
180     return word;
181 }
182
183 /**
184  * Switch copy command, prepared by other functions, to shadow variable,
185  * convert command to MSB,
186  * transfer command to DIN
187  * store spi response
188  * return spi response
189  */
190 int din_spi_transfer_mst() {
191     port_desc_t* desc;
192     din_spi_cmd_sh = din_spi_cmd;
193     desc = hal_port_get_dsc(PORT_NAME_DINSPI, -1);
194     uint32_t commands[3];
195     commands[0] = (din_spi_cmd_sh & 0xFF0000) >> 16;
196     commands[1] = (din_spi_cmd_sh & 0xFF00) >> 8;
197     commands[2] = (din_spi_cmd_sh & 0xFF);
198
199     din_spi_resp = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
200     return din_spi_resp;
201 }
202
203 /**
204  * Transfer prepared commands through spi
205  * With highest priority send state modification commands
206  * With secondary priority send interrupt commands
207  * In the end send other commands
208  *
209  * Store response from spi
210  * Returns spi response
211  */
212 int din_spi_transfer() {
213     if (transfer_state_cmd) {
214         din_spi_cmd = pin_st_p_cmd;
215         din_spi_transfer_mst();
216         din_spi_cmd = pin_st_g_cmd;
217         transfer_state_cmd = 0;
218     }
219     else if (transfer_interrupt_cmd) {
220         din_spi_cmd = pin_int_p_cmd;
221         din_spi_transfer_mst();
222         din_spi_cmd = pin_int_g_cmd;
223         transfer_interrupt_cmd = 0;
224     }
225     return din_spi_transfer_mst();
226 }
227
228 /**
229  * Get latest response from SPI. Function does not send anything.
230  * @return latest spi response
231  */
232 int din_spi_response() {
233     return din_spi_resp;
234 }
235
236 /**
237  * Get last command sent on SPI
238  * @return latest sent command
239  */
240 int din_spi_get_cmd() {
241     return din_spi_cmd;
242 }