4 * Created on: 17.12.2012
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
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;
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;
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};
41 const static uint32_t dsc_pin_map[8U] = {
53 // See mcp4922.pdf p. 24
55 // Bit 13: Output Gain Selection bit set = 1x (VOUT = VREF * D/4096)
56 // Bit 15: DACA (0) or DACB (1) Selection bit.
57 #define DACA_INIT_VAL (_BV(13) | _BV(12) )
58 #define DACB_INIT_VAL (_BV(13) | _BV(12) | _BV(15))
60 int8_t drv_din_ref(uint16_t ref_a, uint16_t ref_b)
66 port_desc_t* desc = hal_port_get_dsc(PORT_NAME_DACDREF, -1);
68 // Send command for DAC A
69 cmd = DACA_INIT_VAL | (ref_a & 0x0FFF);
71 commands[0] = (cmd & 0xFF00) >> 8;
72 commands[1] = (cmd & 0xFF);
73 desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
75 // Send command for DAC B
76 cmd = DACB_INIT_VAL | (ref_b & 0x0FFF);
78 commands[0] = (cmd & 0xFF00) >> 8;
79 commands[1] = (cmd & 0xFF);
80 desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
82 // Fixme: check SPI return value.
87 int8_t drv_din_get_varthr(uint8_t pin) {
90 if((pin < 8) || (pin > 15)) {
94 return hal_gpio_pin_get_value(dsc_pin_map[pin - 8]);
98 * Set programmable pin DIN_SP according bits in argument as switch-to-battery (1) or switch-to-ground(0)
99 * @param word 8-bit array representing switch-to state
101 void din_set_pr(uint8_t word) {
104 din_spi_cmd = 1 << 16; // Settings command
106 for (i = 0; i < 8; i++, word >>= 1) {
109 din_spi_cmd |= 1 << din_set_pin_pr_i[i];
112 din_spi_cmd &= ~(1 << din_set_pin_pr_i[i]);
118 * Set DIN pins to be tri-state (1) or Active (0)
119 * @param sp_state 16-bit variable representing state of SP pins. (0 - active, 1 - tri-state).
120 * @param sg_state 16-bit variable representing state of SG pins. (0 - active, 1 - tri-state).
122 void din_set_stat(uint16_t sp_state, uint16_t sg_state) {
125 uint32_t state = (sp_state&0xFF)|((sg_state&0xFF)<<8);
126 uint32_t* pin_cmd_ptr = NULL;
127 pin_st_p_cmd = 0x9 << 16; // Set command for SP pins
128 pin_st_g_cmd = 0xA << 16; // Set command for SG pins
129 for (i = 0; i < 16; i++,state >>= 1) {
131 if (i < 8) { // First 8 pins SP0 - SP7
132 pin_cmd_ptr = &pin_st_p_cmd;
134 else { // Another 8 pins SG0 - SG7
135 pin_cmd_ptr = &pin_st_g_cmd;
139 *pin_cmd_ptr |= 1 << din_set_pin_st_i[i];
142 *pin_cmd_ptr &= ~(1 << din_set_pin_st_i[i]);
145 transfer_state_cmd = 1; // Enable transfer of two commands at once
149 * Enable/disable interrupts for DIN pins as well as acting pins as wake-up
150 * @param sp_int_enable 16-bit variable representing interrupt enablers for SP pins (0 - disable wake-up and interrupt, 1 - enable interrupt).
151 * @param sg_int_enable 16-bit variable representing interrupt enablers for SG pins (0 - disable wake-up and interrupt, 1 - enable interrupt).
153 void din_set_int(uint16_t sp_int_enable, uint16_t sg_int_enable) {
156 uint32_t int_enable = (sp_int_enable&0xFF)|((sg_int_enable&0xFF)<<8); // LSB
157 uint32_t* pin_cmd_ptr = NULL;
158 pin_int_p_cmd = 0x2 << 16; // Set command for SP pins
159 pin_int_g_cmd = 0x3 << 16; // Set command for SG pins
160 for (i = 0; i < 16; i++,int_enable >>= 1) {
161 val = int_enable&0x1;
162 if (i < 8) { // First 8 pins SP0 - SP7
163 pin_cmd_ptr = &pin_int_p_cmd;
165 else { // Another 8 pins SG0 - SG7
166 pin_cmd_ptr = &pin_int_g_cmd;
170 *pin_cmd_ptr |= 1 << din_set_pin_st_i[i];
173 *pin_cmd_ptr &= ~(1 << din_set_pin_st_i[i]);
176 transfer_interrupt_cmd = 1; // Enable transfer of two commands at once
180 * Prepare reset command to be sent through spi
183 din_spi_cmd = 0x7F0000;
187 * Prepare switch status command to be sent through spi
189 void din_switch_st() {
194 * Get values of all DIN pins in form of 16-bit word DIN15,...,DIN0
195 * @return values of all pins.
197 uint16_t din_get_val_word()
200 //uint16_t sp = ((din_spi_resp >> 14) & 0x00FF);
201 //uint16_t sg = ((din_spi_resp << 8 ) & 0xFF00);
203 // How it actually is.
204 // Ignore datasheet, this is the actual response from the SPI driver:
205 // [xxxx xxxx][SG7-SG0][SP1 SP0 yy yyyy][zz SP7-SP2]
207 // y: Maybe SG13-SG8, but untested.
208 // z: Maybe therm flag and int flag.
209 // For SP: First get SP7-SP2 right, then add SP1 and SP0
210 uint16_t sp = ((din_spi_resp << 2) & 0x00FF) | ((din_spi_resp >> 14) & 0x3);
211 uint16_t sg = ((din_spi_resp >> 8) & 0xFF00);
212 uint16_t word = sg | sp;
217 * Switch copy command, prepared by other functions, to shadow variable,
218 * convert command to MSB,
219 * transfer command to DIN
221 * return spi response
223 int din_spi_transfer_mst() {
225 din_spi_cmd_sh = din_spi_cmd;
226 desc = hal_port_get_dsc(PORT_NAME_DINSPI, -1);
227 uint32_t commands[3];
228 commands[0] = (din_spi_cmd_sh & 0xFF0000) >> 16;
229 commands[1] = (din_spi_cmd_sh & 0xFF00) >> 8;
230 commands[2] = (din_spi_cmd_sh & 0xFF);
232 din_spi_resp = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
237 * Transfer prepared commands through spi
238 * With highest priority send state modification commands
239 * With secondary priority send interrupt commands
240 * In the end send other commands
242 * Store response from spi
243 * Returns spi response
245 int din_spi_transfer() {
246 if (transfer_state_cmd) {
247 din_spi_cmd = pin_st_p_cmd;
248 din_spi_transfer_mst();
249 din_spi_cmd = pin_st_g_cmd;
250 transfer_state_cmd = 0;
252 else if (transfer_interrupt_cmd) {
253 din_spi_cmd = pin_int_p_cmd;
254 din_spi_transfer_mst();
255 din_spi_cmd = pin_int_g_cmd;
256 transfer_interrupt_cmd = 0;
258 return din_spi_transfer_mst();
262 * Get latest response from SPI. Function does not send anything.
263 * @return latest spi response
265 int din_spi_response() {
270 * Get last command sent on SPI
271 * @return latest sent command
273 int din_spi_get_cmd() {