]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/din.c
Uncrustify
[pes-rpp/rpp-lib.git] / rpp / src / drv / din.c
1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Michal Horn <hornmich@fel.cvut.cz>
5  *     - Martin Koubek <martin.koubek@porsche-engineering.com>
6  *
7  * This document contains proprietary information belonging to Czech
8  * Technical University in Prague. Passing on and copying of this
9  * document, and communication of its contents is not permitted
10  * without prior written authorization.
11  *
12  * File : din.c
13
14  * Abstract:
15  *     This file is written for 33972 Multiple Switch
16  *     http://www.freescale.com/files/analog/doc/data_sheet/MC33972.pdf
17  *
18  *     This file contains functions to control DIN
19  *     Voltage on each pin can be set
20  *     switch to ground or to battery on programable pins can be set
21  *     interrupts on each pins can be disabled and enabled
22  */
23
24
25 /******************************************************************************
26 *   Include Files
27 ******************************************************************************/
28 #include "drv/drv.h"
29 #include "drv/port.h"
30 #include "drv/gio_tab.h"
31
32
33 /******************************************************************************
34 *   Static Variable Definitions
35 ******************************************************************************/
36 /**
37  * Stored response from SPI.
38  *
39  * The response data does not depend on the command sent.
40  */
41 static uint8_t din_spi_resp[3];
42
43 /** Store commands in shadow registers */
44 static uint16_t shadow_reg_list[DIN_NUM_SPI_CMD];
45
46 /******************************************************************************
47 *   Function Prototypes
48 ******************************************************************************/
49 static int din_spi_transfer_mst(const uint32_t din_spi_cmd);
50
51 /******************************************************************************
52 *   Close variable declaration sections
53 ******************************************************************************/
54 /* Private defines */
55 /* --------------- */
56 /** Options: */
57 /**   Bit 13: Output Gain Selection bit set = 1x (VOUT = VREF * D/4096)   */
58 /**   Bit 15: DACA (0) or DACB (1) Selection bit.  */
59 #define DACA_INIT_VAL   (_BV(13) | _BV(12)          )
60 #define DACB_INIT_VAL   (_BV(13) | _BV(12) | _BV(15))
61
62 /**
63  * This find an index in register list
64  * @param command
65  * @return index
66  */
67 static uint32_t enum2cmd(const enum SpiCmdTable index)
68 {
69         if (index == DIN_RESET_CMD)
70                 return 0x007F0000;
71         else
72                 return index << 16;
73 }
74
75 /* Public functions */
76 /* ---------------- */
77
78 uint16_t din_set_reg(
79         enum SpiCmdTable spi_cmd_index, uint16_t clear_mask, uint16_t xor_mask)
80 {
81         if (spi_cmd_index >= DIN_NUM_SPI_CMD)
82                 return 0;
83
84         shadow_reg_list[spi_cmd_index] =
85                 shadow_reg_list[spi_cmd_index] & ~clear_mask ^ xor_mask;
86
87         uint32_t din_spi_cmd = enum2cmd(spi_cmd_index) | shadow_reg_list[spi_cmd_index];
88
89         return din_spi_transfer_mst(din_spi_cmd);
90 }
91
92 int8_t drv_din_ref(uint16_t ref_a, uint16_t ref_b)
93 {
94
95         uint16_t cmd;
96         char commands[2];
97         const struct port_desc *port = &port_desc[PORT_ID_DACDREF];
98
99         // Send command for DAC A
100         cmd = DACA_INIT_VAL | (ref_a & 0x0FFF);
101
102         commands[0] = (cmd & 0xFF00) >> 8;
103         commands[1] = (cmd & 0xFF);
104         port->set(port, commands, sizeof(commands));
105
106         // Send command for DAC B
107         cmd = DACB_INIT_VAL | (ref_b & 0x0FFF);
108
109         commands[0] = (cmd & 0xFF00) >> 8;
110         commands[1] = (cmd & 0xFF);
111         port->set(port, commands, sizeof(commands));
112
113         // Fixme: check SPI return value.
114         return SUCCESS;
115 }
116
117 STATIC_ASSERT(PIN_DIN8  - 0 == PIN_DIN8 &&
118                           PIN_DIN9  - 1 == PIN_DIN8 &&
119                           PIN_DIN10 - 2 == PIN_DIN8 &&
120                           PIN_DIN11 - 3 == PIN_DIN8 &&
121                           PIN_DIN12 - 4 == PIN_DIN8 &&
122                           PIN_DIN13 - 5 == PIN_DIN8 &&
123                           PIN_DIN14 - 6 == PIN_DIN8 &&
124                           PIN_DIN15 - 7 == PIN_DIN8
125                           ,
126                           DIN_pins_are_contiguous); /* The following function relies on this */
127
128
129 int8_t drv_din_get_varthr(uint8_t pin)
130 {
131
132         // Check range
133         if ((pin < 8) || (pin > 15))
134                 return FAILURE;
135
136         /* TODO: Move this function to rpp layer and use rpp_gio_get() */
137         return gio_tab_get(PIN_DIN8 + (pin - 8)) ? 1 : 0;
138 }
139
140 uint16_t din_get_val_word()
141 {
142         // How it should be.
143         //uint16_t sp = ((din_spi_resp >> 14) & 0x00FF);
144         //uint16_t sg = ((din_spi_resp << 8 ) & 0xFF00);
145
146         // How it actually is.
147         // Ignore datasheet, this is the actual response from the SPI driver:
148         // [xxxx xxxx][SG7-SG0][SP1 SP0 yy yyyy][zz SP7-SP2]
149         //  x: Unknown.
150         //  y: Maybe SG13-SG8, but untested.
151         //  z: Maybe therm flag and int flag.
152         // For SP: First get SP7-SP2 right, then add SP1 and SP0
153         uint16_t sp = (din_spi_resp[0] << 2) | (din_spi_resp[1] >> 6);
154         uint16_t sg = din_spi_resp[2];
155         uint16_t word = (sg << 8) | sp;
156
157         return word;
158 }
159
160 /* Private functions */
161 /* ----------------- */
162 /**
163  * Switch copy command, prepared by other functions, to shadow variable,
164  * convert command to MSB,
165  * transfer command to DIN
166  * store spi response
167  * return spi response
168  */
169 static int din_spi_transfer_mst(const uint32_t din_spi_cmd)
170 {
171         const struct port_desc *port = &port_desc[PORT_ID_DINSPI];
172
173         char commands[3];
174
175         commands[0] = (din_spi_cmd & 0xFF0000) >> 16;   // command
176         commands[1] = (din_spi_cmd & 0xFF00) >> 8;      // 1.st B of data
177         commands[2] = (din_spi_cmd & 0xFF);             // 2.nd B of data
178
179         int8_t ret = port->set(port, commands, sizeof(commands));
180         if (ret == FAILURE)
181                 return FAILURE;
182
183         STATIC_ASSERT(sizeof(commands) == sizeof(din_spi_resp), din_spi_buffer_size_missmatch);
184         memcpy(din_spi_resp, commands, sizeof(din_spi_resp));
185
186         return SUCCESS;
187 }