Jakub Tomanek / Mbed 2 deprecated TPS92520_TEST_v2

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
pinnarelo
Date:
Mon Dec 10 09:19:37 2018 +0000
Parent:
6:4e6ec83d3c83
Commit message:
TPS92520

Changed in this revision

TPS92520/TPS92520.cpp Show annotated file Show diff for this revision Revisions of this file
TPS92520/TPS92520.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 4e6ec83d3c83 -r a52c300451ed TPS92520/TPS92520.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TPS92520/TPS92520.cpp	Mon Dec 10 09:19:37 2018 +0000
@@ -0,0 +1,355 @@
+/***************************************************************************//**
+*   @file    TPS92520.c
+*   @brief   TPS92520 implementation file.
+*   @devices TPS92520-Q1
+*
+********************************************************************************
+* Copyright 2018(c) Automotive Lighting
+*
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  - 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.
+*  - Neither the name of Automotive Lighting nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*  - The use of this software may or may not infringe the patent rights
+*    of one or more patent holders.  This license does not release you
+*    from the requirement that you obtain separate licenses from these
+*    patent holders to use this software.
+*  - Use of the software either in source or binary form, must be run
+*    on or directly connected to an Automotive Lighting component.
+*
+* THIS SOFTWARE IS PROVIDED BY AUTOMOTIVE LIGHTING "AS IS" AND ANY EXPRESS OR 
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, 
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL AUTOMOTIVE LIGHTING BE LIABLE FOR ANY DIRECT, INDIRECT, 
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+* INTELLECTUAL PROPERTY RIGHTS, 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.
+*******************************************************************************/
+
+/******************************************************************************/
+/***************************** Include Files **********************************/
+/******************************************************************************/
+#include "mbed.h"
+#include "TPS92520.h"
+
+
+/* Error codes */
+#define INVALID_VAL -1 /* Invalid argument */
+#define COMM_ERR    -2 /* Communication error on receive */
+#define TIMEOUT     -3 /* A timeout has occured */
+
+/* SPI CLK Frequency */
+#if not definated
+    #define SPI_CLK 100000
+#endif
+
+TPS92520::TPS92520(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName pwr_en) : my_spi(mosi, miso, sclk), my_pin( cs), pwr_en_pin(pwr_en) { }
+
+TPS92520::~TPS92520() { }
+
+
+/***************************************************************************//**
+* @brief Reads the junction temperature 
+*
+* @return pointer to string message.
+*******************************************************************************/
+char* TPS92520::temp(void) {
+    int ret;
+    int low,high = 0;
+    static char buffer[20];
+    sprintf(buffer, "\0");
+    
+    /* TEMPL Register */                        
+    ret = readRegs(TEMPL,&low);
+    if(ret<0) {
+        sprintf(buffer, "COMM ERROR\n\r");
+        return buffer; }
+    low = low & 0x0003;
+    
+    /* TEMPH Register */                        
+    ret = readRegs(TEMPH,&high);
+    if(ret<0) {
+        sprintf(buffer, "COMM ERROR\n\r");
+        return buffer; }
+    high = high & 0x00FF;
+    
+    high = high << 2;
+    high = high + low;
+    
+    float temp = 0.7168*high-274.51;
+    sprintf(buffer, "Temp Junction: %0.1f\r\n", temp);
+        
+    return buffer;
+}
+
+/***************************************************************************//**
+* @brief Reads value from all status registers and create message with all 
+*       errors 
+*
+* @return pointer to string message.
+*******************************************************************************/
+char* TPS92520::status(void) {
+    int ret;
+    int raw_data,c = 0;
+    static char buffer[200];
+    sprintf(buffer, "\0");
+    
+    char *reports1[8] = {"CH2LSILIM", "CH2HSILIM", "CH2SHORT", "CH2COMPOV",
+                             "CH1LSILIM", "CH1HSILIM", "CH1SHORT", "CH1COMPOV"};
+                             
+    char *reports2[6] = {"CH2TP", "CH2BSTUV", "CH2TOFFMIN",
+                            "CH1TP", "CH1BSTUV", "CH1TOFFMIN"};
+    
+    char *reports3[7] = {"V5AUV", "Watchdog Expired", "Watchdog Expired",
+                            "TW", "PC", "CH2STATUS","CH1STATUS"};
+    
+    readRegs(STATUS3,&raw_data);
+    
+    /* STATUS 1 Register */                        
+    ret = readRegs(STATUS1,&raw_data);
+    if(ret<0) {
+        sprintf(buffer, "COMM ERROR\n\r");
+        return buffer; }
+    raw_data = raw_data & 0x00FF;
+    for(int i = 0; i<8; i++) {
+        c = raw_data & 1 <<i;
+        if(c>0) {
+            strcat(buffer, reports1[7-i]);
+            strcat(buffer, "\r\n");
+            }
+        }
+    
+    /* STATUS 2 Register */                        
+    ret = readRegs(STATUS2,&raw_data);
+    if(ret<0) {
+        sprintf(buffer, "COMM ERROR\n\r");
+        return buffer; }
+    raw_data = raw_data & 0x00FF;
+    for(int i = 0; i<6; i++) {
+        c = raw_data & 1 <<i;
+        if(c>0) {
+            strcat(buffer, reports2[5-i]);
+            strcat(buffer, "\r\n");
+            }
+        }
+        
+    /* STATUS 3 Register */                        
+    ret = readRegs(STATUS3,&raw_data);
+    if(ret<0) {
+        sprintf(buffer, "COMM ERROR\n\r");
+        return buffer; }
+    raw_data = raw_data & 0x00FF;
+    for(int i = 0; i<7; i++) {
+        c = raw_data & 1 <<i;
+        if(c>0) {
+            strcat(buffer, reports3[6-i]);
+            strcat(buffer, "\r\n");
+            }
+        }
+    
+    if(buffer[0] == '\0') sprintf(buffer, "OK\r\n");
+        
+    return buffer;
+}
+
+/***************************************************************************//**
+* @brief Init SPI periphery 
+*
+*******************************************************************************/
+void TPS92520::init(void) {
+    // Setup the spi for 16 bit data, Mode 0 CLK polarity 0, Phase 0
+    my_spi.format(16,0);
+    my_spi.frequency(SPI_CLK);
+    // Enable 5VA PWR supply
+    pwr_en_pin = 1;
+    
+    int data; 
+    /* Check STATUS3 Register */                        
+    readRegs(STATUS3,&data);
+    
+    
+}
+
+
+/***************************************************************************//**
+* @brief Read register value.
+*
+* @param addr  - The address of the register.
+* @param pData - Pointer to the data which hold readed register data
+*
+* @return Returns 0 for success or negative error code. 
+*
+*******************************************************************************/
+int TPS92520::readRegs(int addr, int *pData) {
+    uint8_t CMD = 0;
+    uint16_t frame = 0;
+    
+    frame = CMD<<15 | addr<<9 | 0x00;
+    frame = frame | parity(frame)<<8;
+    
+    /* First Frame */
+    my_pin = 0;
+    my_spi.write(frame);
+    my_pin = 1;
+    wait_us(10);
+    
+    /* Second Frame */
+    my_pin = 0;
+    uint16_t rx_buffer = my_spi.write(frame);
+    my_pin = 1;
+    
+    /* Response is valid in the second frame @ Datasheet */
+    *pData = rx_buffer;
+    
+    if(rx_buffer & SPI_ERROR == TRUE) return COMM_ERR;
+    
+    if((rx_buffer & 0x7C00)>>10 != 24) return COMM_ERR;
+    
+    return 0;
+
+    }
+
+/***************************************************************************//**
+* @brief Write register value.
+*
+* @param addr  - The address of the register.
+* @param data  - The data to be writen.
+* @param response - Pointer to the data which hold writen register data
+*
+* @return Returns 0 for success or negative error code. 
+*
+*******************************************************************************/    
+int TPS92520::writeRegs(int addr, int data, int *response) {
+    uint8_t CMD = 1;
+    uint16_t frame = 0;
+    
+    frame = CMD<<15 | addr<<9 | data;
+    frame = frame | parity(frame)<<8;
+    
+    /* First Frame */
+    my_pin = 0;
+    my_spi.write(frame);
+    my_pin = 1;
+    wait_us(10);
+    
+    /* Second Frame */
+    my_pin = 0;
+    uint16_t rx_buffer = my_spi.write(frame);
+    my_pin = 1;
+    
+    /* Response is valid in the second frame @ Datasheet */
+    *response = rx_buffer;
+    
+    if(rx_buffer & SPI_ERROR == TRUE) return COMM_ERR;
+    
+    if((rx_buffer & 0x00FF) != data) return COMM_ERR;
+    
+    if((rx_buffer & 0x3F00)>>8 != addr) return COMM_ERR;
+      
+    return 0;
+
+    }
+
+/***************************************************************************//**
+* @brief Reset device. This function clear all writeable register to their 
+*                   default value.
+*
+* @return Returns 0. 
+*
+*******************************************************************************/     
+int TPS92520::reset() {
+    int data;
+  
+    // Disable 5VA PWR supply
+    pwr_en_pin = 0;
+    wait_ms(350);
+    
+    // Enable 5VA PWR supply
+    pwr_en_pin = 1;
+    
+    wait_ms(50);
+    /* Check STATUS3 Register */                        
+    readRegs(STATUS3,&data);
+
+    return 0;   
+    }    
+
+/***************************************************************************//**
+* @brief Calculate parity bit.
+*
+* @param frame  - The frame for which we want to calculate parity bit.
+*
+* @return Returns parity bit value. 
+*
+*******************************************************************************/  
+int TPS92520::parity(uint16_t frame) {
+    uint8_t XNOR = 0;
+    
+    for(int i = 15; i >= 0; i--){
+        if((frame & (1 << i)) != 0){
+            XNOR = !(XNOR^1);
+            if(i == 15){
+                XNOR = 1; }
+            }
+        else{
+            XNOR = !(XNOR^0);
+            if(i == 15){
+                XNOR = 0; }
+           } 
+        }
+    return XNOR;
+    }
+
+/***************************************************************************//**
+* @brief Set the PWM duty.
+*
+* @param 
+*
+* @return  
+*
+*******************************************************************************/     
+int TPS92520::setPWMduty(uint8_t channel,uint16_t duty) {
+    uint8_t CMD = 1;
+    
+    if(duty> 1023 == 1) return INVALID_VAL;
+    
+    uint16_t data = (uint16_t)duty/100*1023;
+    uint16_t frame = 0;
+    
+    // First SPI frame
+    uint8_t addr = CH1PWMH;
+    if (channel == 2) addr +=2; 
+    
+    frame = CMD<<15 | addr<<9 | data&0x0300>>8;
+    frame = frame | parity(frame)<<8;
+    
+    my_pin = 0;
+    uint16_t rx_buffer = my_spi.write(frame);
+    my_pin = 1;
+    
+    // Second SPI frame
+    addr = CH1PWML;
+    if (channel == 2) addr +=2; 
+    
+    frame = CMD<<15 | addr<<9 | data&0x00FF;
+    frame = frame | parity(frame)<<8;
+
+    my_pin = 0;
+    rx_buffer = my_spi.write(frame);
+    my_pin = 1;
+        
+    return 0;
+
+    } 
\ No newline at end of file
diff -r 4e6ec83d3c83 -r a52c300451ed TPS92520/TPS92520.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TPS92520/TPS92520.h	Mon Dec 10 09:19:37 2018 +0000
@@ -0,0 +1,158 @@
+/***************************************************************************//**
+*   @file    TPS92520.h
+*   @brief   TPS92520 header file.
+*   @devices TPS92520-Q1
+*
+********************************************************************************
+* Copyright 2018(c) Automotive Lighting
+*
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  - 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.
+*  - Neither the name of Automotive Lighting nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*  - The use of this software may or may not infringe the patent rights
+*    of one or more patent holders.  This license does not release you
+*    from the requirement that you obtain separate licenses from these
+*    patent holders to use this software.
+*  - Use of the software either in source or binary form, must be run
+*    on or directly connected to an Automotive Lighting component.
+*
+* THIS SOFTWARE IS PROVIDED BY AUTOMOTIVE LIGHTING "AS IS" AND ANY EXPRESS OR 
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, 
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL AUTOMOTIVE LIGHTING BE LIABLE FOR ANY DIRECT, INDIRECT, 
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+* INTELLECTUAL PROPERTY RIGHTS, 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.
+*******************************************************************************/
+
+#ifndef __TPS92520_H__
+#define __TPS92520_H__
+
+/******************************************************************************/
+/***************************** Include Files **********************************/
+/******************************************************************************/
+#include "mbed.h"
+#include <stdint.h>
+
+
+/** TPS92520 class
+ *
+ *  TPS92520: A library
+ *
+ *  TPS92520 is an LED Driver
+ *  @endcode
+ */
+ 
+class TPS92520
+{
+public:
+
+    /** Create a TPS92520 instance
+     *  which is connected to specified SPI pins
+     *
+     * @param mosi SPI MOSI pin
+     * @param miso SPI MISO pin
+     * @param sclk SPI SCLK pin
+     */
+    TPS92520(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName pwr_en);
+
+    /** Destructor of BME280
+     */
+    virtual ~TPS92520();
+
+    void init(void);
+    
+    int readRegs(int addr, int *pData);
+    
+    int writeRegs(int addr, int data, int *response);
+    
+    int reset(void);
+    
+    int setPWMduty(uint8_t channel,uint16_t duty);
+    
+    char* status(void);
+    
+    char* temp(void);
+
+private:
+
+    SPI         my_spi;
+    DigitalOut  my_pin;
+    DigitalOut  pwr_en_pin;
+    
+    int TPS92520::parity(uint16_t frame);
+};
+
+/* TPS92520-Q1 Register Map */
+#define SYSCFG1     0x00
+#define SYSCFG2     0x01
+#define CMWTAP      0x02
+#define STATUS1     0x03
+#define STATUS2     0x04
+#define STATUS3     0x05
+#define TWLMT       0x06
+#define SLEEP       0x07
+#define CH1IADJL    0x08
+#define CH1IADJH    0x09
+#define CH2IADJL    0x0A
+#define CH2IADJH    0x0B
+#define PWMDIV      0x0C
+#define CH1PWML     0x0D
+#define CH1PWMH     0x0E
+#define CH2PWML     0x0F
+#define CH2PWMH     0x10
+#define CH1TON      0x11
+#define CH2TON      0x12
+#define CH1VIN      0x13
+#define CH1VLED     0x14
+#define CH1VLEDON   0x15
+#define CH1VLEDOFF  0x16
+#define CH2VIN      0x17
+#define CH2VLED     0x18
+#define CH2VLEDON   0x19
+#define CH2VLEDOFF  0x1A
+#define TEMPL       0x1B
+#define TEMPH       0x1C
+#define V5D         0x1D
+#define LHCFG1      0x1E
+#define LHCFG2      0x1F
+#define LHIL        0x20
+#define LHIH        0x21
+#define LH1IADJL    0x22
+#define LH1IADJH    0x23
+#define LH2IADJL    0x24
+#define LH2IADJH    0x25
+#define LHCH1PWML   0x26
+#define LHCH1PWMH   0x27
+#define LHCH2PWML   0x28
+#define LHCH2PWMH   0x29
+#define LH1TON      0x2A
+#define LH2TON      0x2B
+#define RESET       0x2C 
+
+/* System Config Register bits */
+#define FPINSRT    (0 << 7)
+
+/* Status Register bits */
+
+
+#define SPI_ERROR     (1 << 15)
+
+#define TRUE 1
+#define FALSE 0
+
+
+#endif /* __TPS92520_H__ */
\ No newline at end of file
diff -r 4e6ec83d3c83 -r a52c300451ed main.cpp
--- a/main.cpp	Wed Sep 13 11:30:50 2017 +0000
+++ b/main.cpp	Mon Dec 10 09:19:37 2018 +0000
@@ -1,12 +1,148 @@
 #include "mbed.h"
+#include <string> // this should be already included in <sstream>
+#include "TPS92520.h"
 
+
+TPS92520 LedDriver(PA_7, PA_6, PA_5, PA_4, PA_0);
+
+Serial pc(SERIAL_TX, SERIAL_RX);
 DigitalOut myled(LED1);
 
+DigitalOut CH1_PWM(PA_1);
+DigitalOut CH2_PWM(PA_3);
+
+volatile char   c = '\0'; // Initialized to the NULL character
+
+void Rx_interrupt();
+void read_line();
+int hex2int(char ch);
+
+// Circular buffers for serial TX and RX data - used by interrupt routines
+const int buffer_size = 255;
+// might need to increase buffer size for high baud rates
+char rx_buffer[buffer_size+1];
+// Circular buffer pointers
+// volatile makes read-modify-write atomic 
+volatile int rx_in=0;
+volatile int rx_out=0;
+// Line buffers for sprintf and sscanf
+char rx_line[80];
+
+// Receive Buffer 
+char buffer[50];
+ 
 int main() {
+ 
+    pc.baud(9600);
+    pc.attach(&Rx_interrupt, Serial::RxIrq);
+    pc.printf("TPS92520 Test Software\n\r");
+
+    
+    // Enable Led Channels
+    CH1_PWM = 0;
+    CH2_PWM = 0;
+    
+    
+    LedDriver.init();
+    LedDriver.reset();
+    LedDriver.status();
+    
+    int ret, pokus;
+    char buf[50];    
+    
     while(1) {
-        myled = 1; // LED is ON
+        
+        /* Status read TPS92520 */
+        sprintf(buffer, LedDriver.status());
+        if(strncmp(buffer, buf, strlen(buffer))) {
+            strcpy(buf, buffer);
+            pc.printf("Status:\n%s", buf); }
+        
+        /* Status LED */            
+        myled = !myled; 
         wait(0.2); // 200 ms
-        myled = 0; // LED is OFF
-        wait(1.0); // 1 sec
+        
+        /* COM PORT read incoming data */
+        read_line();
+        
     }
 }
+
+
+// Read a line from the large rx buffer from rx interrupt routine
+void read_line() {
+    int i=0;
+    int raw_data = 0;
+    int raw_data2 = 0;
+    int response, ret, ret2;
+    // Loop reading rx buffer characters until end of line character
+    while ((i==0) || (rx_line[i-1] != '\r')) {
+        // Wait if buffer empty
+        if (rx_in == rx_out) {
+            return;
+        }
+        rx_line[i] = rx_buffer[rx_out];
+        i++;
+        rx_out = (rx_out + 1) % buffer_size;
+    }
+    rx_line[i-1] = 0;
+    if(strncmp(rx_line,"W",1)== 0) {
+        
+        int address = 16*hex2int(rx_line[2])+hex2int(rx_line[3]);
+        int data = 16*hex2int(rx_line[5])+hex2int(rx_line[6]);
+        
+        pc.printf("Writing register: Address: %d\r\n", address);
+        pc.printf("Writing register: Data: %d\r\n", data);
+        ret = LedDriver.writeRegs(address, data, &response);
+        if(ret < 0) printf("Error Code A: %d\r\n", ret);
+        pc.printf("Writen Data: %d\r\n", response & 0x00FF);
+    }
+    else if(strncmp(rx_line,"R",1)== 0) {
+        
+        int address = 16*hex2int(rx_line[2])+hex2int(rx_line[3]);
+        
+        pc.printf("Reading register: Address: %d\r\n", address);
+        ret = LedDriver.readRegs(address, &raw_data);
+        if(ret < 0) printf("Error Code A: %d\r\n", ret);
+
+        pc.printf("Register data: %d\r\n", raw_data & 0x00FF);
+    }
+    else if(strncmp(rx_line,"reset",5) == 0) {
+        ret = LedDriver.reset();
+        pc.printf("Reseting device\r\n");
+        if(ret < 0) printf("Error Code: %d\r\n", ret); }
+    else if(strncmp(rx_line,"stat",4) == 0) {
+        pc.printf("%s", LedDriver.status()); }
+    else if(strncmp(rx_line,"temp",4) == 0) {
+        pc.printf("%s", LedDriver.temp()); }
+    else {
+        pc.printf("Invalid Command\r\n"); 
+    }
+    
+    return;
+}
+
+
+// Interupt Routine to read in data from serial port
+void Rx_interrupt() {
+    // Loop just in case more than one character is in UART's receive FIFO buffer
+    // Stop if buffer full
+    while ((pc.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
+        rx_buffer[rx_in] = pc.getc();
+        // Uncomment to Echo to USB serial to watch data flow
+        // pc.putc(rx_buffer[rx_in]);
+        rx_in = (rx_in + 1) % buffer_size;
+    }
+    return;
+}
+
+int hex2int(char ch)
+{
+    if (ch >= '0' && ch <= '9')
+        return ch - '0';
+    if (ch >= 'A' && ch <= 'F')
+        return ch - 'A' + 10;
+    if (ch >= 'a' && ch <= 'f')
+        return ch - 'a' + 10;
+    return -1;
+}