Liqun Wu / Mbed 2 deprecated 90418_mbed_controller

Dependencies:   mbed

Revision:
0:be95bfb06686
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scpi-def.cpp	Mon Jan 17 13:20:09 2022 +0000
@@ -0,0 +1,504 @@
+/*-
+ * BSD 2-Clause License
+ *
+ * Copyright (c) 2012-2018, Jan Breuer
+ * 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.
+ *
+ * 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 HOLDER 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   scpi-def.c
+ * @date   Thu Nov 15 10:58:45 UTC 2012
+ *
+ * @brief  SCPI parser test
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "types.h"
+#include "uart_mbed.h"
+#include "main_init.h"
+#include "i2c_mbed_fpga.h"
+#include "scpi/scpi.h"
+#include "scpi/parser.h"
+#include "scpi-def.h"
+#include "i2c_ram_defines.h"
+#include "nv_bitfield_map.h"
+//#include "test_vector.h"
+#include "test_fg.h"
+#include "test_ehp_reg.h"
+#include "mbed.h"
+
+extern i2c_mbed_fpga i2c;
+LocalFileSystem local("local"); 
+
+static void reprogram_for_server()
+{
+    i2c.i2c_word_write_simple((0x1018-0x1000)/2, 0x2080 );
+    i2c.i2c_word_write_simple((0x101A-0x1000)/2, 0xfc13);
+    i2c.i2c_word_write_simple((0x101C-0x1000)/2, 0x7eb ); 
+    i2c.i2c_word_write_simple((0x1022-0x1000)/2, 0x2073); 
+    i2c.i2c_word_write_simple((0x1024-0x1000)/2, 0x1ff); 
+    i2c.i2c_word_write_simple((0x1026-0x1000)/2, 0xc); 
+    i2c.i2c_word_write_simple((0x1028-0x1000)/2, 0x800); 
+    i2c.i2c_word_write_simple((0x103A-0x1000)/2, 0xfff); 
+    i2c.i2c_word_write_simple((0x103C-0x1000)/2, 0x1); 
+    i2c.i2c_word_write_simple((0x003E)/2, 0x1); 
+    i2c.i2c_word_write_simple((0x1040-0x1000)/2, 0x0); 
+    i2c.i2c_word_write_simple((0x1042-0x1000)/2, 0x0); 
+    i2c.i2c_word_write_simple((0x1044-0x1000)/2, 0x7f); 
+    i2c.i2c_word_write_simple((0x1046-0x1000)/2, 0x7f7f); 
+    i2c.i2c_word_write_simple((0x1050-0x1000)/2, 0x700);    
+}
+
+static uint16_t word_read_helper(uint16_t address)
+{
+    uint16_t value;
+    if((address >= 0x1000) && (address < 0x1200)) {
+        address = (address - 0x1000) / 2;
+        i2c.i2c_word_read_simple(address, &value);
+    } else {
+        i2c.i2c_word_read_interpreter(address, &value);
+    }
+    return value;
+}
+
+static scpi_result_t set_duty(scpi_t * context) {
+    float input = 0;
+    int32_t duty_cycle_scaled = 0;
+
+    /* read first parameter if present */
+    if (!SCPI_ParamFloat(context, &input, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+    duty_cycle_scaled = ((int)(input * 65535.0)) / 100u;
+    i2c.i2c_set_open_loop_duty(duty_cycle_scaled);
+    return SCPI_RES_OK;
+}
+
+scpi_result_t get_duty(scpi_t* context)
+{
+    float duty_percentage;
+    uint16_t duty_cycle;
+    i2c.i2c_word_read_simple(I2C_SPEED_DUTY, &duty_cycle);
+    duty_percentage = ((float)duty_cycle)/655.35;
+    SCPI_ResultFloat(context, duty_percentage);
+    return SCPI_RES_OK;
+}
+
+
+const scpi_choice_def_t led_selects[] = {
+    { "OFF", 0 },
+    { "ON", 1 },
+    SCPI_CHOICE_LIST_END
+};
+static scpi_result_t set_led1(scpi_t * context) {
+    int32_t input = 0;
+
+    if (!SCPI_ParamChoice(context, led_selects, &input, TRUE))
+        return SCPI_RES_ERR;
+
+    led1 = input;
+    return SCPI_RES_OK;
+}
+
+scpi_result_t get_led1(scpi_t* context)
+{
+    int led_value = led1;
+    SCPI_ResultText(context, led_selects[led_value].name);
+    return SCPI_RES_OK;
+}
+
+
+scpi_result_t read_word(scpi_t* context)
+{
+    uint32_t address = 0;
+    uint16_t value;
+
+    /* read first parameter if present */
+    if (!SCPI_ParamUInt32(context, &address, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+    value = word_read_helper((uint16_t)address);
+
+    SCPI_ResultUInt16Base(context, value, 16);
+    return SCPI_RES_OK;
+}
+
+scpi_result_t write_word(scpi_t* context)
+{
+    int32_t address = 0;
+    int32_t value = 0;
+
+    /* read first parameter: address */
+    if (!SCPI_ParamInt(context, &address, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    /* read first parameter: address */
+    if (!SCPI_ParamInt(context, &value, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    if((address >= 0x1000) && (address < 0x1200)) {
+        address = (address - 0x1000) / 2;
+        if(address == 15){   /* Special if-case for the windmilling debugging, writing the default registers */
+            i2c.i2c_word_write_simple(address, value);
+            reprogram_for_server();   
+        }
+        else { /* Normal write operation */
+            i2c.i2c_word_write_simple(address, value);
+        }
+    } else {
+        i2c.i2c_word_write_interpreter(address, value);
+    }
+    return SCPI_RES_OK;
+}
+
+scpi_result_t read_array(scpi_t* context)
+{
+    uint32_t start_address = 0;
+    uint32_t size = 0;
+
+    /* read first parameter: start address */
+    if (!SCPI_ParamUInt32(context, &start_address, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    /* read second parameter: size */
+    if (!SCPI_ParamUInt32(context, &size, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    if(((size % 2) != 0u) || (size == 0)) {
+        SCPI_ErrorPush(context,SCPI_ERROR_ILLEGAL_PARAMETER_VALUE);
+        return SCPI_RES_ERR;
+    }
+
+    uint16_t array[(size/2)];  // uint16_t* array = (uint16_t*)malloc(size);
+    uint16_t index = 0;
+    for(index = 0u; index < (size/2); index++) {
+        array[index] = word_read_helper(start_address + (index * 2));
+    }
+
+    SCPI_ResultArrayUInt16(context, array, (sizeof(array) / sizeof(*array)), SCPI_FORMAT_ASCII);
+    return SCPI_RES_OK;
+}
+
+scpi_result_t repeat_read(scpi_t* context)
+{
+    uint32_t interval_us;
+    uint32_t first_address;
+    uint32_t second_address;
+    uint32_t samples;
+
+    /* read first parameter: size */
+    if (!SCPI_ParamUInt32(context, &samples, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    if (!SCPI_ParamUInt32( context, &interval_us, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+
+    /* The first address. This is mandatory */
+    if (!SCPI_ParamUInt32(context, &first_address, TRUE)) {
+        return SCPI_RES_ERR;
+    }
+    /* A potential second address. Optional */
+    if (!SCPI_ParamUInt32(context, &second_address, FALSE)) {
+        second_address = 0;
+    }
+
+    if(second_address != 0) {
+        uint16_t array[samples*2];  // uint16_t* array = (uint16_t*)malloc(size);
+
+        for(uint32_t index = 0u; index < samples*2; index=index+2) {
+            array[index] = word_read_helper(first_address);
+            array[index+1] = word_read_helper(second_address);
+            wait_us(interval_us);
+        }
+        SCPI_ResultArrayUInt16(context, array, (sizeof(array) / sizeof(*array)), SCPI_FORMAT_ASCII);
+    } else {
+        uint16_t array[samples];  // uint16_t* array = (uint16_t*)malloc(size);
+
+        for(uint32_t index = 0u; index < samples; index++) {
+            array[index] = word_read_helper(first_address);
+            wait_us(interval_us);
+        }
+        SCPI_ResultArrayUInt16(context, array, (sizeof(array) / sizeof(*array)), SCPI_FORMAT_ASCII);
+    }
+
+    return SCPI_RES_OK;
+}
+
+scpi_result_t dump_ram(scpi_t* context)
+{
+    uint16_t start_address  = 0x1000;
+    uint16_t end_address    = 0x1096;
+    uint16_t data;
+
+      
+    FILE *RAMdump = fopen("/local/RAMdump.csv", "w");  // Open "RAMdump.csv" on the local file system (on the mbed) for writing    
+    led4 = !led4;  
+    wait_us(500000);  
+    for (uint16_t address=start_address ; address<=end_address-2; address=address+2)
+    {
+        data = word_read_helper((uint16_t)address);
+        fprintf(RAMdump, "0x%.4X,0x%.4X\r\n", address, data);     // Write each address and read data of the complete RAM to the external file 
+    }
+    fclose(RAMdump);
+    led4 = !led4;  
+    return SCPI_RES_OK;
+}
+
+scpi_result_t reset_config_mode(scpi_t* context)
+{
+    main_init();
+    //wait_us(2000000);         /* keep FPGA in reset for 2s, to let motor stop */
+    wait_us(100);               /* reset the IO-pin for minimum few us */
+    enable_fpga();              /* enable FPGA */
+    i2c.wait_for_idle_state();  /* wait for FPGA responsive */
+    //wait_us(1000);
+    wait_us(100);
+    i2c.i2c_config_mode_entry();/* enter configuration mode */
+    return SCPI_RES_OK;
+}
+
+scpi_result_t reset_htol_mode(scpi_t* context)
+{
+    i2c.i2c_soft_reset();
+    i2c.wait_for_idle_state();  /* wait for FPGA responsive */
+    //wait_us(1000);
+    wait_us(100);
+    i2c.i2c_mlx_mode_entry(); /* Enter melexis mode */
+    wait_us(100);
+    i2c.i2c_htol_mode_entry(); /* Enter HTOL mode */
+    return SCPI_RES_OK;
+}
+
+
+const scpi_choice_def_t mlxmode_selects[] = {
+    { "OFF", 0 },
+    { "ON", 1 },
+    SCPI_CHOICE_LIST_END
+};
+scpi_result_t reset_application_mode(scpi_t* context)
+{
+    int32_t mlxmode = 0;
+    if (!SCPI_ParamChoice(context, mlxmode_selects, &mlxmode, FALSE))
+        mlxmode = 0;
+    main_init();
+    wait_us(2000000);   /* keep FPGA in reset for 5s, to let motor stop*/
+    enable_fpga();   /* enable FPGA */
+    if(mlxmode == 1) {
+        i2c.wait_for_idle_state();
+        wait_us(1000);
+        i2c.i2c_mlx_mode_entry();
+    }
+    i2c.wait_for_application_state();
+    wait_us(1000);
+    return SCPI_RES_OK;
+}
+
+scpi_result_t soft_reset_application_mode(scpi_t* context)
+{
+    int32_t mlxmode = 0;
+    if (!SCPI_ParamChoice(context, mlxmode_selects, &mlxmode, FALSE))
+        mlxmode = 0;
+    i2c.i2c_soft_reset();
+    if(mlxmode == 1) {
+        i2c.wait_for_idle_state();
+        wait_us(100);
+        i2c.i2c_mlx_mode_entry();
+        i2c.wait_for_application_state();
+    }
+    wait_us(100);
+    return SCPI_RES_OK;
+}
+
+/* 
+*   self-test routines
+*/
+
+scpi_result_t test_capture_position_timing(scpi_t* context)
+{
+    /*to be added*/
+    reset_fpga(); /*finish*/
+    return SCPI_RES_OK;
+}
+
+scpi_result_t test_ehp_reg_vector(scpi_t* context)
+{
+
+    /*vector start, use template later: TBD*/
+    led3=1;
+    test_ehp_reg test(p15,p16);
+    test.configure();
+    test.run();
+    test.stop();
+    SCPI_ResultArrayUInt32(context, test.getResult(), test.getBufferSize(), SCPI_FORMAT_ASCII);
+    SCPI_ResultText(context, test.getResultStatus() );
+    test.release();
+    
+    /*
+    test_vector* t;
+    test_ehp_reg test(p15,p16); //p15 to capture timer -> non_flat.  p16 to trigger ADC sample
+    t = &test;
+    t->configure();
+    t->run();
+    t->stop();
+    SCPI_ResultArrayUInt32(context, t->getResult(), t->getBufferSize(), SCPI_FORMAT_ASCII);
+    SCPI_ResultText(context, t->getResultStatus() );
+    t->release();
+    */
+    led3=0;
+    return SCPI_RES_OK;
+}
+
+scpi_result_t test_fg_vector(scpi_t* context)
+{
+     /*vector start, use template later: TBD*/
+    led3=1;
+    test_fg test(p15);
+    test.configure();
+    test.run();
+    test.stop();
+    SCPI_ResultArrayUInt32(context, test.getResult(), test.getBufferSize(), SCPI_FORMAT_ASCII);
+    SCPI_ResultText(context, test.getResultStatus() );
+    test.release();
+    /*
+    test_vector* t;
+    test_fg test(p15); //only two option to capture: p15 is CAP3.0  or p16 is CAP3.1
+    t = &test;
+    t->configure();
+    t->run();
+    t->stop();
+    SCPI_ResultArrayUInt32(context, t->getResult(), t->getBufferSize(), SCPI_FORMAT_ASCII);
+    SCPI_ResultText(context, t->getResultStatus() );
+    t->release();
+    */
+    led3=0;
+    return SCPI_RES_OK; 
+}
+
+/**
+ * Reimplement IEEE488.2 *TST?
+ *
+ * Result should be 0 if everything is ok
+ * Result should be 1 if something goes wrong
+ *
+ * Return SCPI_RES_OK
+ */
+static scpi_result_t My_CoreTstQ(scpi_t * context) {
+
+    SCPI_ResultInt(context, 0);
+    
+    
+    return SCPI_RES_OK;
+}
+
+void configure_scpi(void)
+{
+    /* user_context will be pointer to socket */
+    SCPI_Init(&scpi_context,
+            scpi_commands,
+            &scpi_interface,
+            scpi_units_def,
+            "Melexis", "MLX90418", NULL, "0",
+            scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH,
+            scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE);
+}
+
+
+const scpi_command_t scpi_commands[] = {
+    /* IEEE Mandated Commands (SCPI std V1999.0 4.1.1) */
+    {"*CLS", SCPI_CoreCls, 0},
+    {"*ESE", SCPI_CoreEse, 0},
+    {"*ESE?", SCPI_CoreEseQ, 0},
+    {"*ESR?", SCPI_CoreEsrQ, 0},
+    {"*IDN?", SCPI_CoreIdnQ, 0},
+    {"*OPC", SCPI_CoreOpc, 0},
+    {"*OPC?", SCPI_CoreOpcQ, 0},
+    {"*RST", SCPI_CoreRst, 0},
+    {"*SRE", SCPI_CoreSre, 0},
+    {"*SRE?", SCPI_CoreSreQ, 0},
+    {"*STB?", SCPI_CoreStbQ, 0},
+    {"*TST?", My_CoreTstQ, 0},
+    {"*WAI", SCPI_CoreWai, 0},
+
+    /* Required SCPI commands (SCPI std V1999.0 4.2.1) */
+    {"SYSTem:ERRor[:NEXT]?", SCPI_SystemErrorNextQ, 0},
+    {"SYSTem:ERRor:COUNt?", SCPI_SystemErrorCountQ, 0},
+    {"SYSTem:VERSion?", SCPI_SystemVersionQ, 0},
+
+    //{"STATus:OPERation?", scpi_stub_callback, 0},
+    //{"STATus:OPERation:EVENt?", scpi_stub_callback, 0},
+    //{"STATus:OPERation:CONDition?", scpi_stub_callback, 0},
+    //{"STATus:OPERation:ENABle", scpi_stub_callback, 0},
+    //{"STATus:OPERation:ENABle?", scpi_stub_callback, 0},
+
+    {"STATus:QUEStionable[:EVENt]?", SCPI_StatusQuestionableEventQ, 0},
+    //{"STATus:QUEStionable:CONDition?", scpi_stub_callback, 0},
+    {"STATus:QUEStionable:ENABle", SCPI_StatusQuestionableEnable, 0},
+    {"STATus:QUEStionable:ENABle?", SCPI_StatusQuestionableEnableQ, 0},
+
+    {"STATus:PRESet", SCPI_StatusPreset, 0},
+
+    /* DMM */
+    {"TARGet:DUTYcycle", set_duty, 0},
+    {"TARGet:DUTYcycle?", get_duty, 0},
+    {"TARGet:SPEED", set_duty, 0},
+    {"TARGet:SPEED?", get_duty, 0},
+    {"LED1", set_led1, 0},
+    {"LED1?", get_led1, 0},
+    {"MEMory:WORD?", read_word, 0},
+    {"MEMory:WORD", write_word, 0},
+    {"MEMory:ARRAY?", read_array, 0},
+    {"MEMory:REPEAT?", repeat_read, 0},
+    {"MEMory:DUMPRAM", dump_ram, 0},
+    {"SYSTem:RESET[:APPLImode]", reset_application_mode, 0},
+    {"SYSTem:SOFTRESET[:APPLImode]", soft_reset_application_mode, 0},
+    {"SYSTem:RESET:CONFIGmode", reset_config_mode, 0},
+    {"SYSTem:RESET:HTOLmode", reset_htol_mode, 0},
+    {"TEST:POSItion", test_capture_position_timing, 0},
+    {"TEST:TESTfg", test_fg_vector, 0},
+    {"TEST:TESTehpreg", test_ehp_reg_vector, 0},
+
+    SCPI_CMD_LIST_END
+};
+
+scpi_interface_t scpi_interface = {
+    /*.error = */ SCPI_Error,
+    /*.write = */ SCPI_Write,
+    /*.control = */ SCPI_Control,
+    /*.flush = */ SCPI_Flush,
+    /*.reset = */ SCPI_Reset,
+};
+
+char scpi_input_buffer[SCPI_INPUT_BUFFER_LENGTH];
+scpi_error_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE];
+scpi_t scpi_context;