From 54150a8f62d57bd3af5efce1439ba3c29e20f07f Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 26 Mar 2011 01:04:10 +0000 Subject: Incorporate changes from Uros Platise git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3419 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/configs/vsn/src/sif.c | 502 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 nuttx/configs/vsn/src/sif.c (limited to 'nuttx/configs/vsn/src/sif.c') diff --git a/nuttx/configs/vsn/src/sif.c b/nuttx/configs/vsn/src/sif.c new file mode 100644 index 000000000..cdd7967f9 --- /dev/null +++ b/nuttx/configs/vsn/src/sif.c @@ -0,0 +1,502 @@ +/**************************************************************************** + * config/vsn/src/sif.c + * arch/arm/src/board/sif.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * + * Authors: Uros Platise + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** \file + * \author Uros Platise + * \brief VSN Sensor Interface + * + * Public interface: + * - sif_init(): should be called just once after system starts, to + * initialize internal data structures, device driver and hardware + * - individual starts() and stops() that control gpio, usart, i2c, ... + * are wrapped throu open() and close() + * - read() and write() are used for streaming + * - ioctl() for configuration + * + * STDOUT Coding 16-bit (little endian): + * - MSB = 0 GPIOs, followed by the both GPIO config bytes + * - MSB = 1 Input AD, centered around 0x4000 + * + * STDIN Coding 16-bit (little endian): + * - MSB = 0 GPIOs, followed by the both GPIO config bytes + * - MSB-1 = 0 Analog Output (PWM or Power) + * - MSB-1 = 1 Analog Reference Tap + * + * GPIO Update cycle: + * - if they follow the Analog Output, they are synced with them + * - if they follow the Analog Reference Tap, they are synced with them + * - if either is configured without sample rate value, they are updated + * immediately, same as them + * + * Implementation: + * - Complete internal states and updateing is made via the struct + * vsn_sif_s, which is also accessible thru the ioctl() with + * SNP Message descriptor. + **/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "vsn.h" + + +/**************************************************************************** + * Declarations and Structures + ****************************************************************************/ + +#define VSN_SIF_READ_BUFSIZE 128 +#define VSN_SIF_WRITE_BUFSIZE 128 + + +typedef unsigned char vsn_sif_state_t; + +# define VSN_SIF_STATE_POWERDOWN 0x00 ///< power-down + +# define VSN_SIF_STATE_ACT_GPIO 0x01 ///< gpio is active +# define VSN_SIF_STATE_ACT_USART 0x02 ///< usart is active +# define VSN_SIF_STATE_ACT_I2C 0x04 ///< i2c is active +# define VSN_SIF_STATE_ACT_OWIR1 0x08 ///< 1-wire is active on first GPIO +# define VSN_SIF_STATE_ACT_OWIR2 0x10 ///< 1-wire is active on second GPIO + +# define VSN_SIF_STATE_ACT_ANOUT 0x20 ///< analog output is active +# define VSN_SIF_STATE_ACT_ANIN 0x40 ///< analog input is active + + +typedef unsigned char vsn_sif_gpio_t; + +# define VSN_SIF_GPIO_STATE_MASK 7 +# define VSN_SIF_GPIO_HIGHZ 0 ///< High-Z +# define VSN_SIF_GPIO_PULLUP 1 ///< Pull-Up +# define VSN_SIF_GPIO_PULLDOWN 2 ///< Pull-Down +# define VSN_SIF_GPIO_OUTLOW 3 ///< Set Low +# define VSN_SIF_GPIO_OUTHIGH 4 ///< Set High + +# define VSN_SIF_GPIO_DISALT_MASK 0x10 ///< Disable Alternate Function, Mask Bit +# define VSN_SIF_GPIO_TRIG_MASK 0x20 ///< Send data change to the stdout +# define VSN_SIF_GPIO_READ_MASK 0x40 ///< Readout mask + + +#define VSN_SIF_ANOUT_LOW 0 // Pseudo Analog Output acts as GPIO +#define VSN_SIF_ANOUT_HIGH 1 // Pseudo Analog Output acts as GPIO high +#define VSN_SIF_ANOUT_HIGHPWR 2 // ... acts as high power output +#define VSN_SIF_ANOUT_PWM 3 // ... acts as PWM output +#define VSN_SIF_ANOUT_PWMPWR 4 // acts as power PWM output + +#define VSN_SIF_ANIN_GAINMASK 7 +#define VSN_SIF_ANIN_GAIN1 0 +#define VSN_SIF_ANIN_GAIN2 1 +#define VSN_SIF_ANIN_GAIN4 2 +#define VSN_SIF_ANIN_GAIN8 3 +#define VSN_SIF_ANIN_GAIN16 4 +#define VSN_SIF_ANIN_GAIN32 5 +#define VSN_SIF_ANIN_GAIN64 6 +#define VSN_SIF_ANIN_GAIN128 7 + +#define VSN_SIF_ANIN_BITS8 +#define VSN_SIF_ANIN_BITS9 +#define VSN_SIF_ANIN_BITS10 +#define VSN_SIF_ANIN_BITS11 +#define VSN_SIF_ANIN_BITS12 +#define VSN_SIF_ANIN_BITS13 +#define VSN_SIF_ANIN_BITS14 + +#define VSN_SIF_ANIN_OVERSMP1 +#define VSN_SIF_ANIN_OVERSMP2 +#define VSN_SIF_ANIN_OVERSMP4 +#define VSN_SIF_ANIN_OVERSMP8 +#define VSN_SIF_ANIN_OVERSMP16 + + +struct vsn_sif_s { + vsn_sif_state_t state; // activity + unsigned char opencnt; // open count + + vsn_sif_gpio_t gpio[2]; + + unsigned char anout_opts; + unsigned short int anout_width; + unsigned short int anout_period; // setting it to 0, disables PWM + unsigned short int anout_samplerate; // as written by write() + + unsigned short int anref_width; + unsigned short int anref_period; // setting it to 0, disables PWM + unsigned short int anref_samplerate; // as written by write() + + unsigned char anin_opts; + unsigned int anin_samplerate; // returned on read() as 16-bit results + + /*--- Private Data ---*/ + + struct stm32_tim_dev_s * tim3; // Timer3 is used for PWM, and Analog RefTap + struct stm32_tim_dev_s * tim8; // Timer8 is used for Power Switch + + sem_t exclusive_access; +}; + + +/**************************************************************************** + * Private data + ****************************************************************************/ + +struct vsn_sif_s vsn_sif; + + +/**************************************************************************** + * Semaphores + ****************************************************************************/ + +void sif_sem_wait(void) +{ + while( sem_wait( &vsn_sif.exclusive_access ) != 0 ) { + ASSERT(errno == EINTR); + } +} + + +void inline sif_sem_post(void) +{ + sem_post( &vsn_sif.exclusive_access ); +} + + +/**************************************************************************** + * GPIOs and Alternative Functions + ****************************************************************************/ + + +void sif_gpios_reset(void) +{ + vsn_sif.gpio[0] = vsn_sif.gpio[1] = VSN_SIF_GPIO_HIGHZ; + + stm32_configgpio(GPIO_GP1_HIZ); + stm32_configgpio(GPIO_GP2_HIZ); +} + + +void sif_gpio1_update(void) +{ + uint32_t val; + + switch(vsn_sif.gpio[0] & VSN_SIF_GPIO_STATE_MASK) { + case VSN_SIF_GPIO_HIGHZ: val = GPIO_GP1_HIZ; break; + case VSN_SIF_GPIO_PULLUP: val = GPIO_GP1_PUP; break; + case VSN_SIF_GPIO_PULLDOWN: val = GPIO_GP1_PDN; break; + case VSN_SIF_GPIO_OUTLOW: val = GPIO_GP1_LOW; break; + case VSN_SIF_GPIO_OUTHIGH: val = GPIO_GP1_HIGH;break; + default: return; + } + stm32_configgpio(val); + + if ( stm32_gpioread(val) ) + vsn_sif.gpio[0] |= VSN_SIF_GPIO_READ_MASK; + else vsn_sif.gpio[0] &= ~VSN_SIF_GPIO_READ_MASK; +} + + +void sif_gpio2_update(void) +{ + uint32_t val; + + switch(vsn_sif.gpio[1]) { + case VSN_SIF_GPIO_HIGHZ: val = GPIO_GP2_HIZ; break; + case VSN_SIF_GPIO_PULLUP: val = GPIO_GP2_PUP; break; + case VSN_SIF_GPIO_PULLDOWN: val = GPIO_GP2_PDN; break; + case VSN_SIF_GPIO_OUTLOW: val = GPIO_GP2_LOW; break; + case VSN_SIF_GPIO_OUTHIGH: val = GPIO_GP2_HIGH;break; + default: return; + } + stm32_configgpio(val); + + if ( stm32_gpioread(val) ) + vsn_sif.gpio[1] |= VSN_SIF_GPIO_READ_MASK; + else vsn_sif.gpio[1] &= ~VSN_SIF_GPIO_READ_MASK; +} + + +int sif_gpios_lock(vsn_sif_state_t peripheral) +{ + return ERROR; +} + + +int sif_gpios_unlock(vsn_sif_state_t peripheral) +{ + return ERROR; +} + + +/**************************************************************************** + * Analog Outputs + ****************************************************************************/ + +static volatile int test = 0, test_irq; + + +static int sif_anout_isr(int irq, void *context) +{ + STM32_TIM_ACKINT(vsn_sif.tim8, 0); + + test++; + test_irq = irq; + + return OK; +} + + +int sif_anout_init(void) +{ + vsn_sif.tim3 = stm32_tim_init(3); + vsn_sif.tim8 = stm32_tim_init(8); + + if (!vsn_sif.tim3 || !vsn_sif.tim8) return ERROR; + + // Use the TIM3 as PWM modulated analogue output + + STM32_TIM_SETCHANNEL(vsn_sif.tim3, GPIO_OUT_PWM_TIM3_CH4, STM32_TIM_CH_OUTPWM | STM32_TIM_CH_POLARITY_NEG); + STM32_TIM_SETPERIOD(vsn_sif.tim3, 4096); + STM32_TIM_SETCOMPARE(vsn_sif.tim3, GPIO_OUT_PWM_TIM3_CH4, 1024); + + STM32_TIM_SETCLOCK(vsn_sif.tim3, 36e6); + STM32_TIM_SETMODE(vsn_sif.tim3, STM32_TIM_MODE_UP); + stm32_configgpio(GPIO_OUT_HIZ); + + // Use the TIM8 to drive the upper power mosfet + + STM32_TIM_SETISR(vsn_sif.tim8, sif_anout_isr, 0); + STM32_TIM_ENABLEINT(vsn_sif.tim8, 0); + + STM32_TIM_SETCHANNEL(vsn_sif.tim8, GPIO_OUT_PWRPWM_TIM8_CH1P, STM32_TIM_CH_OUTPWM | STM32_TIM_CH_POLARITY_NEG); + STM32_TIM_SETPERIOD(vsn_sif.tim8, 4096); + STM32_TIM_SETCOMPARE(vsn_sif.tim8, GPIO_OUT_PWRPWM_TIM8_CH1P, 0); + + STM32_TIM_SETCLOCK(vsn_sif.tim8, 36e6); + STM32_TIM_SETMODE(vsn_sif.tim8, STM32_TIM_MODE_UP); + stm32_configgpio(GPIO_OUT_PWRPWM); + + return OK; +} + + +void sif_anout_update(void) +{ +} + + +void sif_anout_callback(void) +{ + // called at rate of PWM interrupt +} + + +/**************************************************************************** + * Analog Input Reference Tap + ****************************************************************************/ + + +void sif_anref_init(void) +{ +} + + +/**************************************************************************** + * Analog Input Sampler Unit + ****************************************************************************/ + + +void sif_anin_reset(void) +{ +} + + +/**************************************************************************** + * Device driver functions + ****************************************************************************/ + +int devsif_open(FAR struct file *filep) +{ + sif_sem_wait(); + vsn_sif.opencnt++; + + // Start Hardware + + sif_sem_post(); + return 0; +} + + +int devsif_close(FAR struct file *filep) +{ + sif_sem_wait(); + + if (--vsn_sif.opencnt) { + + // suspend (powerdown) hardware + + sif_gpios_reset(); + + //STM32_TIM_SETCLOCK(vsn_sif.tim3, 0); + //STM32_TIM_SETCLOCK(vsn_sif.tim8, 0); + } + + sif_sem_post(); + return 0; +} + + +static ssize_t devsif_read(FAR struct file *filp, FAR char *buffer, size_t len) +{ + sif_sem_wait(); + memset(buffer, 0, len); + sif_sem_post(); + return len; +} + + +static ssize_t devsif_write(FAR struct file *filp, FAR const char *buffer, size_t len) +{ + sif_sem_wait(); + printf("getpid: %d\n", getpid() ); + sif_sem_post(); + return len; +} + + +#ifndef CONFIG_DISABLE_POLL +static int devsif_poll(FAR struct file *filp, FAR struct pollfd *fds, + bool setup) +{ + if (setup) { + fds->revents |= (fds->events & (POLLIN|POLLOUT)); + + if (fds->revents != 0) { + sem_post(fds->sem); + } + } + return OK; +} +#endif + + +int devsif_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + sif_sem_wait(); + sif_sem_post(); + return 0; +} + + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + +static const struct file_operations devsif_fops = { + devsif_open, /* open */ + devsif_close, /* close */ + devsif_read, /* read */ + devsif_write, /* write */ + 0, /* seek */ + devsif_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , devsif_poll /* poll */ +#endif +}; + + +/** Bring up the Sensor Interface by initializing all of the desired + * hardware components. + **/ + +int sif_init(void) +{ + /* Initialize data-structure */ + + vsn_sif.state = VSN_SIF_STATE_POWERDOWN; + vsn_sif.opencnt = 0; + sem_init(&vsn_sif.exclusive_access, 0, 1); + + /* Initialize hardware */ + + sif_gpios_reset(); + if ( sif_anout_init() != OK ) return -1; + + /* If everything is okay, register the driver */ + + (void)register_driver("/dev/sif0", &devsif_fops, 0666, NULL); + return OK; +} + + +/** SIF Utility + * + * Provides direct access to the sensor connector, readings, and diagnostic. + **/ + +int sif_main(int argc, char *argv[]) +{ + if (argc >= 2) { + if (!strcmp(argv[1], "init")) { + return sif_init(); + } + else if (!strcmp(argv[1], "gpio") && argc == 4) { + vsn_sif.gpio[0] = atoi(argv[2]); + vsn_sif.gpio[1] = atoi(argv[3]); + sif_gpio1_update(); + sif_gpio2_update(); + printf("GPIO States: %2x %2x\n", vsn_sif.gpio[0], vsn_sif.gpio[1] ); + return 0; + } + else if (!strcmp(argv[1], "pwr") && argc == 3) { + int val = atoi(argv[2]); + STM32_TIM_SETCOMPARE(vsn_sif.tim8, GPIO_OUT_PWRPWM_TIM8_CH1P, val); + return 0; + } + else if (!strcmp(argv[1], "c")) { + } + } + + fprintf(stderr, "%s:\tinit\n\tgpio\tA B\n\tpwr\tval\n", argv[0]); + fprintf(stderr, "test = %.8x, test irq = %.8x\n", test, test_irq); + return -1; +} -- cgit v1.2.3