-/*
- * din.c
+/* Copyright (C) 2012-2013 Czech Technical University in Prague
*
- * Created on: 17.12.2012
- * Author: Michal Horn
+ * Authors:
+ * - Michal Horn <hornmich@fel.cvut.cz>
+ * - Martin Koubek <martin.koubek@porsche-engineering.com>
*
- * This file contains functions to control DIN
- * Voltage on each pin can be set
- * switch to ground or to battery on programable pins can be set
- * interrupts on each pins can be disabled and enabled
+ * This document contains proprietary information belonging to Czech
+ * Technical University in Prague. Passing on and copying of this
+ * document, and communication of its contents is not permitted
+ * without prior written authorization.
+ *
+ * File : din.c
+
+ * Abstract:
+ * This file is written for 33972 Multiple Switch
+ * http://www.freescale.com/files/analog/doc/data_sheet/MC33972.pdf
+ *
+ * This file contains functions to control DIN
+ * Voltage on each pin can be set
+ * switch to ground or to battery on programable pins can be set
+ * interrupts on each pins can be disabled and enabled
*/
-//#include "drv_din.h"
+
+/******************************************************************************
+* Include Files
+******************************************************************************/
#include "drv/drv.h"
-/** Prepared command */
-uint32_t din_spi_cmd = DIN_SPICMD_INIT_VAL;
-/** Shadow variable used during sending */
-uint32_t din_spi_cmd_sh = DIN_SPICMD_INIT_VAL;
+
+
+/******************************************************************************
+* Static Variable Definitions
+******************************************************************************/
/** Stored response from SPI */
-uint32_t din_spi_resp = 0;
-/** Prepared command for change status on SP pins */
-uint32_t pin_st_p_cmd;
-/** Prepared command for change status on SG pins */
-uint32_t pin_st_g_cmd;
-/** Prepared command for disabling interrupt on SP pins */
-uint32_t pin_int_p_cmd;
-/** Prepared command for disabling interrupt on SG pins */
-uint32_t pin_int_g_cmd;
-
-/** Signal for state cmd transfer */
-uint8_t transfer_state_cmd = 0;
-/** Signal for interrupt cmd trasfer */
-uint8_t transfer_interrupt_cmd = 0;
-
-/** Indexes of bits in status commands assigned to pins */
-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};
-/** Indexes of bits in switch-to commands assigned to pins */
-static const uint32_t din_set_pin_pr_i[] = {0, 1, 2, 3, 4, 5, 6, 7};
-/** Indexes of bits in response assigned to pins */
-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};
-
-/*
- * Get DIN pin value.
- * @param pin index of pin according the scheme (0-15)
- * @return value on pin or -1 if error
- */
-int din_get_pin_val(uint32_t pin) {
- if (pin > 15) return -1;
- return ((din_spi_resp & (1 << din_get_pin_val_i[pin])) > 0);
-}
+static uint32_t din_spi_resp = 0;
+
+/** Store commands in shadow registers */
+static uint16_t shadow_reg_list[DIN_NUM_SPI_CMD];
+/******************************************************************************
+* Function Prototypes
+******************************************************************************/
/**
- * Set programmable pin DIN_SP according bits in argument as switch-to-battery (1) or switch-to-ground(0)
- * @param word 8-bit array representing switch-to state
+ * Switch copy command, prepared by other functions, to shadow variable,
+ * convert command to MSB,
+ * transfer command to DIN
+ * store spi response
+ * return spi response
*/
-void din_set_pr(uint8_t word) {
- int i;
- uint8_t val;
- din_spi_cmd = 1 << 16; // Set command
-
- for (i = 0; i < 8; i++,word >>= 1) {
- val = word&0x1;
- if (val == 1) {
- din_spi_cmd |= 1 << din_set_pin_pr_i[i];
- }
- else if (val == 0) {
- din_spi_cmd &= ~(1 << din_set_pin_pr_i[i]);
- }
- }
-}
+int din_spi_transfer_mst(const uint32_t din_spi_cmd);
+
+/******************************************************************************
+* Close variable declaration sections
+******************************************************************************/
+/* Private defines */
+/* --------------- */
+/** Options: */
+/** Bit 13: Output Gain Selection bit set = 1x (VOUT = VREF * D/4096) */
+/** Bit 15: DACA (0) or DACB (1) Selection bit. */
+#define DACA_INIT_VAL (_BV(13) | _BV(12) )
+#define DACB_INIT_VAL (_BV(13) | _BV(12) | _BV(15))
/**
- * Set DIN pins to be tri-state (1) or Active (0)
- * @param sp_state 16-bit variable representing state of SP pins. (0 - active, 1 - tri-state).
- * @param sg_state 16-bit variable representing state of SP pins. (0 - active, 1 - tri-state).
+ * This find an index in register list
+ * @param command
+ * @return index
*/
-void din_set_stat(uint16_t sp_state, uint16_t sg_state) {
- int i;
- uint16_t val;
- uint32_t state = (sp_state&0xFF)|((sg_state&0xFF)<<8);
- uint32_t* pin_cmd_ptr = NULL;
- pin_st_p_cmd = 0x9 << 16; // Set command for SP pins
- pin_st_g_cmd = 0xA << 16; // Set command for SG pins
- for (i = 0; i < 16; i++,state >>= 1) {
- val = state&0x1;
- if (i < 8) { // First 8 pins SP0 - SP7
- pin_cmd_ptr = &pin_st_p_cmd;
- }
- else { // Another 8 pins SG0 - SG7
- pin_cmd_ptr = &pin_st_g_cmd;
- }
-
- if (val) {
- *pin_cmd_ptr |= 1 << din_set_pin_st_i[i];
- }
- else {
- *pin_cmd_ptr &= ~(1 << din_set_pin_st_i[i]);
- }
- }
- transfer_state_cmd = 1; // Enable transfer of two commands at once
+static uint32_t enum2cmd(const enum SpiCmdTable index)
+{
+ if (index == DIN_RESET_CMD)
+ return 0x007F0000;
+ else
+ return index << 16;
}
-/**
- * Enable/disable interrupts for DIN pins as well as acting pins as wake-up
- * @param sp_int_enable 16-bit variable representing interrupt enablers for SP pins (0 - disable wake-up and interrupt, 1 - enable interrupt).
- * @param sg_int_enable 16-bit variable representing interrupt enablers for SG pins (0 - disable wake-up and interrupt, 1 - enable interrupt).
- */
-void din_set_int(uint16_t sp_int_enable, uint16_t sg_int_enable) {
- int i;
- uint16_t val;
- uint32_t int_enable = (sp_int_enable&0xFF)|((sg_int_enable&0xFF)<<8);
- uint32_t* pin_cmd_ptr = NULL;
- pin_int_p_cmd = 0x2 << 16; // Set command for SP pins
- pin_int_g_cmd = 0x3 << 16; // Set command for SG pins
- for (i = 0; i < 16; i++,int_enable >>= 1) {
- val = int_enable&0x1;
- if (i < 8) { // First 8 pins SP0 - SP7
- pin_cmd_ptr = &pin_int_p_cmd;
- }
- else { // Another 8 pins SG0 - SG7
- pin_cmd_ptr = &pin_int_g_cmd;
- }
-
- if (val) {
- *pin_cmd_ptr |= 1 << din_set_pin_st_i[i];
- }
- else {
- *pin_cmd_ptr &= ~(1 << din_set_pin_st_i[i]);
- }
- }
- transfer_interrupt_cmd = 1; // Enable transfer of two commands at once
+/* Public functions */
+/* ---------------- */
+
+uint16_t din_set_reg(
+ enum SpiCmdTable spi_cmd_index, uint16_t clear_mask, uint16_t xor_mask)
+{
+ if (spi_cmd_index >= DIN_NUM_SPI_CMD)
+ return 0;
+
+ shadow_reg_list[spi_cmd_index] =
+ shadow_reg_list[spi_cmd_index] & ~clear_mask ^ xor_mask;
+
+ uint32_t din_spi_cmd = enum2cmd(spi_cmd_index) | shadow_reg_list[spi_cmd_index];
+
+ return din_spi_transfer_mst(din_spi_cmd);
}
-/**
- * Prepare reset command to be sent through spi
- */
-void din_reset() {
- din_spi_cmd = 0x7F0000;
+int8_t drv_din_ref(uint16_t ref_a, uint16_t ref_b)
+{
+
+ uint16_t cmd;
+
+ // Get descriptor
+ uint32_t commands[2];
+ dio_port_desc_t *desc = dio_port_get_dsc(DIO_PORT_NAME_DACDREF, -1);
+
+ // Send command for DAC A
+ cmd = DACA_INIT_VAL | (ref_a & 0x0FFF);
+
+ commands[0] = (cmd & 0xFF00) >> 8;
+ commands[1] = (cmd & 0xFF);
+ desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
+
+ // Send command for DAC B
+ cmd = DACB_INIT_VAL | (ref_b & 0x0FFF);
+
+ commands[0] = (cmd & 0xFF00) >> 8;
+ commands[1] = (cmd & 0xFF);
+ desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
+
+ // Fixme: check SPI return value.
+ return SUCCESS;
}
-/**
- * Prepare switch status command to be sent through spi
- */
-void din_switch_st() {
- din_spi_cmd = 0x0;
+
+int8_t drv_din_get_varthr(uint8_t pin)
+{
+
+ // Check range
+ if ((pin < 8) || (pin > 15))
+ return FAILURE;
+
+ dio_port_desc_t* port = dio_port_get_dsc(DIO_PORT_NAME_DINMCU, -1);
+ if (pin-8 >= port->numValues)
+ return FAILURE;
+
+ return dio_gpio_pin_get_value(port->config[pin - 8]);
}
-/**
- * Get values of all DIN pins in form of 16-bit word DIN15,...,DIN0
- * @return values of all pins DIN0 - DIN15
- */
-uint16_t din_get_val_word() {
- uint16_t word = 0;
- int i;
- for (i = 0; i < 16; i++) {
- word |= din_get_pin_val(i) << i;
- }
- return word;
+uint16_t din_get_val_word()
+{
+ // How it should be.
+ //uint16_t sp = ((din_spi_resp >> 14) & 0x00FF);
+ //uint16_t sg = ((din_spi_resp << 8 ) & 0xFF00);
+
+ // How it actually is.
+ // Ignore datasheet, this is the actual response from the SPI driver:
+ // [xxxx xxxx][SG7-SG0][SP1 SP0 yy yyyy][zz SP7-SP2]
+ // x: Unknown.
+ // y: Maybe SG13-SG8, but untested.
+ // z: Maybe therm flag and int flag.
+ // For SP: First get SP7-SP2 right, then add SP1 and SP0
+ uint16_t sp = ((din_spi_resp << 2) & 0x00FF) | ((din_spi_resp >> 14) & 0x3);
+ uint16_t sg = ((din_spi_resp >> 8) & 0xFF00);
+ uint16_t word = sg | sp;
+
+ return word;
}
+
+int din_spi_response()
+{
+ return din_spi_resp;
+}
+
+
+/* Private functions */
+/* ----------------- */
/**
* Switch copy command, prepared by other functions, to shadow variable,
* convert command to MSB,
* store spi response
* return spi response
*/
-int din_spi_transfer_mst() {
- port_desc_t* desc;
- din_spi_cmd_sh = din_spi_cmd;
- desc = hal_port_get_dsc(PORT_NAME_DINSPI, -1);
- uint32_t commands[3];
- commands[0] = (din_spi_cmd_sh & 0xFF0000) >> 16;
- commands[1] = (din_spi_cmd_sh & 0xFF00) >> 8;
- commands[2] = (din_spi_cmd_sh & 0xFF);
-
- din_spi_resp = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
- return din_spi_resp;
-}
-
-/**
- * Transfer prepared commands through spi
- * With highest priority send state modification commands
- * With secondary priority send interrupt commands
- * In the end send other commands
- *
- * Store response from spi
- * Returns spi response
- */
-int din_spi_transfer() {
- if (transfer_state_cmd) {
- din_spi_cmd = pin_st_p_cmd;
- din_spi_transfer_mst();
- din_spi_cmd = pin_st_g_cmd;
- transfer_state_cmd = 0;
- }
- else if (transfer_interrupt_cmd) {
- din_spi_cmd = pin_int_p_cmd;
- din_spi_transfer_mst();
- din_spi_cmd = pin_int_g_cmd;
- transfer_interrupt_cmd = 0;
- }
- return din_spi_transfer_mst();
-}
-
-/**
- * Get latest response from SPI. Function does not send anything.
- * @return latest spi response
- */
-int din_spi_response() {
- return din_spi_resp;
-}
-
-/**
- * Get last command sent on SPI
- * @return latest sent command
- */
-int din_spi_get_cmd() {
- return din_spi_cmd;
+int din_spi_transfer_mst(const uint32_t din_spi_cmd)
+{
+ dio_port_desc_t *desc;
+
+ desc = dio_port_get_dsc(DIO_PORT_NAME_DINSPI, -1);
+ uint32_t commands[3];
+ commands[0] = (din_spi_cmd & 0xFF0000) >> 16; // command
+ commands[1] = (din_spi_cmd & 0xFF00) >> 8; // 1.st B of data
+ commands[2] = (din_spi_cmd & 0xFF); // 2.nd B of data
+
+ din_spi_resp = desc->port_setfnc_ptr(desc->config, desc->numValues, \
+ commands);
+ return din_spi_resp;
}