1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
4 * - Michal Horn <hornmich@fel.cvut.cz>
5 * - Martin Koubek <martin.koubek@porsche-engineering.com>
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.
15 * This file is written for 33972 Multiple Switch
16 * http://www.freescale.com/files/analog/doc/data_sheet/MC33972.pdf
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
25 /******************************************************************************
27 ******************************************************************************/
30 #include "drv/gio_tab.h"
33 /******************************************************************************
34 * Static Variable Definitions
35 ******************************************************************************/
37 * Stored response from SPI.
39 * The response data does not depend on the command sent.
41 static uint8_t din_spi_resp[3];
43 /** Store commands in shadow registers */
44 static uint16_t shadow_reg_list[DIN_NUM_SPI_CMD];
46 /******************************************************************************
48 ******************************************************************************/
49 static int din_spi_transfer_mst(const uint32_t din_spi_cmd);
51 /******************************************************************************
52 * Close variable declaration sections
53 ******************************************************************************/
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))
63 * This find an index in register list
67 static uint32_t enum2cmd(const enum SpiCmdTable index)
69 if (index == DIN_RESET_CMD)
75 /* Public functions */
76 /* ---------------- */
79 enum SpiCmdTable spi_cmd_index, uint16_t clear_mask, uint16_t xor_mask)
81 if (spi_cmd_index >= DIN_NUM_SPI_CMD)
84 shadow_reg_list[spi_cmd_index] =
85 shadow_reg_list[spi_cmd_index] & ~clear_mask ^ xor_mask;
87 uint32_t din_spi_cmd = enum2cmd(spi_cmd_index) | shadow_reg_list[spi_cmd_index];
89 return din_spi_transfer_mst(din_spi_cmd);
92 int8_t drv_din_ref(uint16_t ref_a, uint16_t ref_b)
97 const struct port_desc *port = &port_desc[PORT_ID_DACDREF];
99 // Send command for DAC A
100 cmd = DACA_INIT_VAL | (ref_a & 0x0FFF);
102 commands[0] = (cmd & 0xFF00) >> 8;
103 commands[1] = (cmd & 0xFF);
104 port->set(port, commands, sizeof(commands));
106 // Send command for DAC B
107 cmd = DACB_INIT_VAL | (ref_b & 0x0FFF);
109 commands[0] = (cmd & 0xFF00) >> 8;
110 commands[1] = (cmd & 0xFF);
111 port->set(port, commands, sizeof(commands));
113 // Fixme: check SPI return value.
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
126 DIN_pins_are_contiguous); /* The following function relies on this */
129 int8_t drv_din_get_varthr(uint8_t pin)
133 if ((pin < 8) || (pin > 15))
136 /* TODO: Move this function to rpp layer and use rpp_gio_get() */
137 return gio_tab_get(PIN_DIN8 + (pin - 8)) ? 1 : 0;
140 uint16_t din_get_val_word()
143 //uint16_t sp = ((din_spi_resp >> 14) & 0x00FF);
144 //uint16_t sg = ((din_spi_resp << 8 ) & 0xFF00);
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]
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;
160 /* Private functions */
161 /* ----------------- */
163 * Switch copy command, prepared by other functions, to shadow variable,
164 * convert command to MSB,
165 * transfer command to DIN
167 * return spi response
169 static int din_spi_transfer_mst(const uint32_t din_spi_cmd)
171 const struct port_desc* port = &port_desc[PORT_ID_DINSPI];
174 commands[0] = (din_spi_cmd & 0xFF0000) >> 16; // command
175 commands[1] = (din_spi_cmd & 0xFF00) >> 8; // 1.st B of data
176 commands[2] = (din_spi_cmd & 0xFF); // 2.nd B of data
178 int8_t ret = port->set(port, commands, sizeof(commands));
182 STATIC_ASSERT(sizeof(commands) == sizeof(din_spi_resp), din_spi_buffer_size_missmatch);
183 memcpy(din_spi_resp, commands, sizeof(din_spi_resp));