Tool/software: TI C/C++ Compiler
HI,
I have to work on MSP430F425. My code in the TI TIDC299 software.
I tried to calibrate the meter but the texas instruments 430 calibrated mass
Turn on red. So there is a communication error. I used a simple terminal to test communication uart which is configured in tidc449 I find that the communication is established correctly and there are messages that I received. I did not understand where the problem is. I think there is a communication between the graphical interface of TI GUI and the code tidc499 which allows to test the communication because there is no problem on the hardware side. I need help to know the instruction in the communication part which is dided to test the communication. Always the graphical interface turning red.
//-------------------------------------------------------------------------- // // Software for MSP430 based e-meters. // // THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR // REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, // INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR // COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE. // TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET // POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY // INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR // YOUR USE OF THE PROGRAM. // // IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL, // CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY // THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED // OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT // OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM. // EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF // REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS // OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF // USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S // AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF // YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS // (U.S.$500). // // Unless otherwise stated, the Program written and copyrighted // by Texas Instruments is distributed as "freeware". You may, // only under TI's copyright in the Program, use and modify the // Program without any charge or restriction. You may // distribute to third parties, provided that you transfer a // copy of this license to the third party and the third party // agrees to these terms by its first use of the Program. You // must reproduce the copyright notice and any other legend of // ownership on each copy or partial copy, of the Program. // // You acknowledge and agree that the Program contains // copyrighted material, trade secrets and other TI proprietary // information and is protected by copyright laws, // international copyright treaties, and trade secret laws, as // well as other intellectual property laws. To protect TI's // rights in the Program, you agree not to decompile, reverse // engineer, disassemble or otherwise translate any object code // versions of the Program to a human-readable form. You agree // that in no event will you alter, remove or destroy any // copyright notice included in the Program. TI reserves all // rights not specifically granted under this license. Except // as specifically provided herein, nothing in this agreement // shall be construed as conferring by implication, estoppel, // or otherwise, upon you, any license or other right under any // TI patents, copyrights or trade secrets. // // You may not use the Program in non-TI devices. // // File: emeter-communications.c // // Steve Underwood <steve-underwood@ti.com> // Texas Instruments Hong Kong Ltd. // // $Id: emeter-communication.c,v 1.8 2007/08/07 05:55:38 a0754793 Exp $ // /*! \file emeter-structs.h */ // //-------------------------------------------------------------------------- // #include <stdint.h> #if !defined(__MSP430__) #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #endif #if defined(__GNUC__) #include <signal.h> #endif #if defined(__MSP430__) #include <io.h> #endif #include <emeter-toolkit.h> #include "emeter.h" #include "emeter-structs.h" #if !defined(NULL) #define NULL (void *) 0 #endif #define MEASURES_ACTIVE_POWER 0x01 #define MEASURES_TRIGONOMETRIC_REACTIVE_POWER 0x02 #define MEASURES_VA_POWER 0x04 #define MEASURES_VRMS 0x08 #define MEASURES_IRMS 0x10 #define MEASURES_POWER_FACTOR 0x20 #define MEASURES_MAINS_FREQUENCY 0x40 #define MEASURES_QUADRATURE_REACTIVE_POWER 0x80 enum host_commands_e { HOST_CMD_GET_METER_CONFIGURATION = 0x56, HOST_CMD_SET_METER_CONSUMPTION = 0x57, HOST_CMD_SET_RTC = 0x58, HOST_CMD_GET_RTC = 0x59, HOST_CMD_SET_PASSWORD = 0x60, HOST_CMD_GET_READINGS_PHASE_1 = 0x61, HOST_CMD_GET_READINGS_PHASE_2 = 0x62, HOST_CMD_GET_READINGS_PHASE_3 = 0x63, HOST_CMD_GET_READINGS_NEUTRAL = 0x64, HOST_CMD_ERASE_FLASH_SEGMENT = 0x70, HOST_CMD_SET_FLASH_POINTER = 0x71, HOST_CMD_FLASH_DOWNLOAD = 0x72, HOST_CMD_FLASH_UPLOAD = 0x73, HOST_CMD_ZAP_MEMORY_AREA = 0x74, HOST_CMD_SUMCHECK_MEMORY = 0x75, HOST_CMD_GET_RAW_POWER_PHASE_1 = 0x91, HOST_CMD_GET_RAW_POWER_PHASE_2 = 0x92, HOST_CMD_GET_RAW_POWER_PHASE_3 = 0x93, HOST_CMD_GET_RAW_REACTIVE_POWER_PHASE_1 = 0x95, HOST_CMD_GET_RAW_REACTIVE_POWER_PHASE_2 = 0x96, HOST_CMD_GET_RAW_REACTIVE_POWER_PHASE_3 = 0x97, HOST_CMD_GET_RAW_POWER_NEUTRAL = 0x99, HOST_CMD_GET_RAW_REACTIVE_POWER_NEUTRAL = 0x9D, HOST_CMD_CHECK_RTC_ERROR = 0xA0, HOST_CMD_RTC_CORRECTION = 0xA1, HOST_CMD_MULTIRATE_SET_PARAMETERS = 0xC0, HOST_CMD_MULTIRATE_GET_PARAMETERS = 0xC1, HOST_CMD_MULTIRATE_CLEAR_USAGE = 0xC2, HOST_CMD_MULTIRATE_GET_USAGE = 0xC3, }; #if defined(__MSP430__) && (defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT)) #define MAX_IEC1107_MSG_BODY 66 typedef union { #if 0 uint8_t uint8[4 + 12 + 256]; uint16_t uint16[(4 + 12 + 256)/2]; #else uint8_t uint8[4 + 12 + MAX_IEC1107_MSG_BODY]; uint16_t uint16[(4 + 12 + MAX_IEC1107_MSG_BODY)/2]; #endif } serial_msg_t; #define IEC1107_MSG_RX_START_BODY 10 #define IEC1107_MSG_RX_START_BODY_W 5 #define IEC1107_MSG_TX_START_BODY 14 #define IEC1107_MSG_TX_START_BODY_W 7 /* Incoming serial message buffer */ serial_msg_t rx_msg; uint8_t rx_msg_len; uint8_t char_timeout_1107; static uint8_t rx_msg_ptr; /* Outgoing serial message buffer */ serial_msg_t tx_msg; uint8_t tx_msg_len; static uint8_t tx_msg_ptr; uint16_t *next_flash_loc; #endif int is_calibration_enabled(void) { return TRUE; } #if IEC1107_D_SUPPORT int iec1107d_status; void send_1107d_report(void) { int i; uint8_t x; uint8_t bcd[5]; const uint8_t *s; static const uint8_t id[] = "/SJJ5eHZSJJ V1.01\r\n"; static const uint8_t serial_number_tag[] = "1-0:0.0.9*255("; static const uint8_t property_number_tag[] = "1-0:0.0.0*255("; static const uint8_t energy_tag[] = "1-0:1.8.0*255("; static const uint8_t status_tag[] = "1-0:96.5.5*255("; static const uint8_t factory_number_tag[] = "0-0:96.1.255*255("; static const uint8_t even_parity[128] = { 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x88, 0x09, 0x0A, 0x8B, 0x0C, 0x8D, 0x8E, 0x0F, 0x90, 0x11, 0x12, 0x93, 0x14, 0x95, 0x96, 0x17, 0x18, 0x99, 0x9A, 0x1B, 0x9C, 0x1D, 0x1E, 0x9F, 0xA0, 0x21, 0x22, 0xA3, 0x24, 0xA5, 0xA6, 0x27, 0x28, 0xA9, 0xAA, 0x2B, 0xAC, 0x2D, 0x2E, 0xAF, 0x30, 0xB1, 0xB2, 0x33, 0xB4, 0x35, 0x36, 0xB7, 0xB8, 0x39, 0x3A, 0xBB, 0x3C, 0xBD, 0xBE, 0x3F, 0xC0, 0x41, 0x42, 0xC3, 0x44, 0xC5, 0xC6, 0x47, 0x48, 0xC9, 0xCA, 0x4B, 0xCC, 0x4D, 0x4E, 0xCF, 0x50, 0xD1, 0xD2, 0x53, 0xD4, 0x55, 0x56, 0xD7, 0xD8, 0x59, 0x5A, 0xDB, 0x5C, 0xDD, 0xDE, 0x5F, 0x60, 0xE1, 0xE2, 0x63, 0xE4, 0x65, 0x66, 0xE7, 0xE8, 0x69, 0x6A, 0xEB, 0x6C, 0xED, 0xEE, 0x6F, 0xF0, 0x71, 0x72, 0xF3, 0x74, 0xF5, 0xF6, 0x77, 0x78, 0xF9, 0xFA, 0x7B, 0xFC, 0x7D, 0x7E, 0xFF, }; /* IEC1107 specifies 7 bit + even parity data. We want to use 8 bit data for calibration, so we use software generation for the parity bit. */ /* If the password is set we are in calibration mode, and the IEC1107D messages should not be sent. After calibration is complete, the password may or may not have been cleared. If it is still set a reset of the MCU will restore normal operation. */ if ((meter_status & PASSWORD_OK)) return; iec1107d_status = 0; if (total_power > 0) iec1107d_status |= 0x80; #if SELF_TEST_SUPPORT if (nv_parms.s.meter_failures != 0xFFFF) // changer iec1107d_status |= 0x01; #endif i = 0; s = id; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; tx_msg.uint8[i++] = even_parity['\r']; tx_msg.uint8[i++] = even_parity['\n']; if (nv_parms.s.property_number[0]) { s = property_number_tag; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; s = nv_parms.s.property_number; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; tx_msg.uint8[i++] = even_parity[')']; tx_msg.uint8[i++] = even_parity['\r']; tx_msg.uint8[i++] = even_parity['\n']; } if (nv_parms.s.serial_number[0]) { s = serial_number_tag; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; s = nv_parms.s.serial_number; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; tx_msg.uint8[i++] = even_parity[')']; tx_msg.uint8[i++] = even_parity['\r']; tx_msg.uint8[i++] = even_parity['\n']; } s = energy_tag; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; last_reported_total_consumed_kwh = total_consumed_kwh; last_reported_total_consumed_100mwh = total_consumed_100mwh; bin2bcd32(bcd, last_reported_total_consumed_kwh); tx_msg.uint8[i++] = even_parity['0' + ((bcd[2] >> 4) & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + (bcd[2] & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + ((bcd[3] >> 4) & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + (bcd[3] & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + ((bcd[4] >> 4) & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + (bcd[4] & 0xF)]; tx_msg.uint8[i++] = even_parity['.']; bin2bcd16(bcd, last_reported_total_consumed_100mwh); tx_msg.uint8[i++] = even_parity['0' + ((bcd[1] >> 4) & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + (bcd[1] & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + ((bcd[2] >> 4) & 0xF)]; tx_msg.uint8[i++] = even_parity['0' + (bcd[2] & 0xF)]; tx_msg.uint8[i++] = even_parity[')']; tx_msg.uint8[i++] = even_parity['\r']; tx_msg.uint8[i++] = even_parity['\n']; s = status_tag; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; x = '0' + ((iec1107d_status >> 4) & 0xF); if (x > '9') x += 7; tx_msg.uint8[i++] = even_parity[x]; x = '0' + (iec1107d_status & 0xF); if (x > '9') x += 7; tx_msg.uint8[i++] = even_parity[x]; tx_msg.uint8[i++] = even_parity[')']; tx_msg.uint8[i++] = even_parity['\r']; tx_msg.uint8[i++] = even_parity['\n']; if (nv_parms.s.factory_number[0]) { s = factory_number_tag; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; s = nv_parms.s.factory_number; while (*s) tx_msg.uint8[i++] = even_parity[*s++]; tx_msg.uint8[i++] = even_parity[')']; tx_msg.uint8[i++] = even_parity['\r']; tx_msg.uint8[i++] = even_parity['\n']; } tx_msg.uint8[i++] = even_parity['!']; tx_msg.uint8[i++] = even_parity['\r']; tx_msg.uint8[i++] = even_parity['\n']; tx_msg_ptr = 0; tx_msg_len = i; #if defined(USART1TX_VECTOR) IE2 |= UTXIE1; #else U0IE |= UTXIE0; #endif } #endif #if defined(__MSP430__) && (defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT)) int send_msg(int len) { if (len > 4 + 12 + MAX_IEC1107_MSG_BODY) return FALSE; tx_msg_ptr = 0; tx_msg_len = len; #if defined(USART1TX_VECTOR) IE2 |= UTXIE1; #else U0IE |= UTXIE0; #endif return TRUE; } int prepare_tx_message(int len) { int i; tx_msg.uint8[0] = 0xFE; tx_msg.uint8[1] = 0xFE; tx_msg.uint8[2] = 0xFE; tx_msg.uint8[3] = 0xFE; tx_msg.uint8[4] = 0x68; tx_msg.uint8[5] = 0x99; tx_msg.uint8[6] = 0x99; tx_msg.uint8[7] = 0x99; tx_msg.uint8[8] = 0x99; tx_msg.uint8[9] = 0x99; tx_msg.uint8[10] = 0x99; tx_msg.uint8[11] = 0x68; tx_msg.uint8[12] = 0x23; tx_msg.uint8[13] = len; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + len] = 0; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + len + 1] = 0x16; for (i = 4; i < IEC1107_MSG_TX_START_BODY + len; i++) tx_msg.uint8[IEC1107_MSG_TX_START_BODY + len] += tx_msg.uint8[i]; return send_msg(IEC1107_MSG_TX_START_BODY + len + 2); } void process_rx_message(serial_msg_t *rx_msg, int rx_len) { int i; int32_t z; int32_t z1; uint16_t *last_flash_loc; /* Messages with type 0x23 are custom messages we use for calibration, password protection, etc. All other message types go to a custom message handler (if available). */ if (rx_msg->uint8[8] != 0x23) { #if CUSTOM_SERIAL_MESSAGE_SUPPORT custom_serial_message_handler(&rx_msg, rx_msg_len); #endif return; } if ((rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] & 0x80)) { /* This looks like one of our own messages, which has echoed back to us */ return; } /* Only process messages if the password has been given correctly (except for the password test message, of course). */ if (!(meter_status & PASSWORD_OK) && rx_msg->uint8[IEC1107_MSG_RX_START_BODY] != 0x60) return; switch (rx_msg->uint8[IEC1107_MSG_RX_START_BODY]) { case HOST_CMD_GET_METER_CONFIGURATION: tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 2] = NUM_PHASES; #if defined(NEUTRAL_MONITOR_SUPPORT) tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 3] = 1; #else tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 3] = 0; #endif tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 4] = 0 #if defined(LIMP_MODE_SUPPORT) | 0x01 #endif #if defined(PHASE_CORRECTION_SUPPORT) | 0x02 #endif #if defined(DYNAMIC_PHASE_CORRECTION_SUPPORT) | 0x04 #endif #if defined(RTC_SUPPORT) | 0x08 #endif #if defined(CORRECTED_RTC_SUPPORT) | 0x10 #endif #if defined(TEMPERATURE_SUPPORT) | 0x20 #endif #if SELF_TEST_SUPPORT | 0x40 #endif #if MULTI_RATE_SUPPORT | 0x80 #endif ; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 5] = MEASURES_ACTIVE_POWER #if defined(REACTIVE_POWER_SUPPORT) && !defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT) | MEASURES_TRIGONOMETRIC_REACTIVE_POWER #endif #if defined(VA_POWER_SUPPORT) | MEASURES_VA_POWER #endif #if defined(VRMS_SUPPORT) | MEASURES_VRMS #endif #if defined(IRMS_SUPPORT) | MEASURES_IRMS #endif #if defined(POWER_FACTOR_SUPPORT) | MEASURES_POWER_FACTOR #endif #if defined(MAINS_FREQUENCY_SUPPORT) | MEASURES_MAINS_FREQUENCY #endif #if defined(REACTIVE_POWER_SUPPORT) && defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT) | MEASURES_QUADRATURE_REACTIVE_POWER #endif ; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 6] = 0x00 #if GAIN_STAGES > 1 | 0x01 #endif ; prepare_tx_message(7); break; case HOST_CMD_SET_METER_CONSUMPTION: z = rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1]; z |= (int32_t) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 2] << 16; z1 = rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 3]; z1 |= (int32_t) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 4] << 16; custom_set_consumption(z, z1); tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; prepare_tx_message(2); case HOST_CMD_SET_RTC: #if defined(RTC_SUPPORT) rtc.year = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 2]; rtc.month = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 3]; rtc.day = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 4]; rtc.hour = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 5]; rtc.minute = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 6]; rtc.second = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 7]; set_rtc_sumcheck(); #endif #if defined(CUSTOM_RTC_SUPPORT) custom_rtc_set(rx_msg->uint8); #endif #if defined(MULTI_RATE_SUPPORT) multirate_align_with_rtc(); #endif tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; prepare_tx_message(2); break; case HOST_CMD_GET_RTC: tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; #if defined(RTC_SUPPORT) tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 2] = rtc.year; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 3] = rtc.month; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 4] = rtc.day; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 5] = rtc.hour; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 6] = rtc.minute; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 7] = rtc.second; #endif #if defined(CUSTOM_RTC_SUPPORT) custom_rtc_retrieve(tx_msg.uint8); #endif #if defined(TEMPERATURE_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = temperature; #endif prepare_tx_message(10); break; case HOST_CMD_SET_PASSWORD: /* Check the calibration password */ if (rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1] == SERIAL_CALIBRATION_PASSWORD_1 && rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 2] == SERIAL_CALIBRATION_PASSWORD_2 && rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 3] == SERIAL_CALIBRATION_PASSWORD_3 && rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 4] == SERIAL_CALIBRATION_PASSWORD_4) { meter_status |= PASSWORD_OK; tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; prepare_tx_message(2); } else { /* Only respond to a bad password, if the password was good before. That lets us know we have unset the password OK, but doesn't give any information to people trying to attack the meter. */ if ((meter_status & PASSWORD_OK)) { tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; prepare_tx_message(2); } meter_status &= ~PASSWORD_OK; } break; case HOST_CMD_GET_READINGS_PHASE_1: #if !defined(SINGLE_PHASE) case HOST_CMD_GET_READINGS_PHASE_2: case HOST_CMD_GET_READINGS_PHASE_3: /* Exchange voltage, current and power readings (neutral). frequency, power factor and reactive power readings. */ phase = &chan[rx_msg->uint8[IEC1107_MSG_RX_START_BODY] - 0x61]; #endif tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; #if defined(VRMS_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->V_rms; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = 0; #endif #if defined(IRMS_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->current.I_rms; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = 0; #endif tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->current.power; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->current.power >> 16; #if defined(REACTIVE_POWER_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->reactive_power; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->reactive_power >> 16; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = 0; #endif #if defined(VA_POWER_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->VA_power; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = phase->VA_power >> 16; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = 0; #endif #if defined(POWER_FACTOR_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = phase->power_factor; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = 0; #endif #if defined(MAINS_FREQUENCY_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = phase->frequency; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = 0; #endif #if defined(LIMP_MODE_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = phase->V_dc_estimate[0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = phase->V_dc_estimate[0] >> 16; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = phase->V_dc_estimate; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = phase->V_dc_estimate >> 16; #endif tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 13] = phase->current.I_dc_estimate[0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 14] = phase->current.I_dc_estimate[0] >> 16; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 30] = 0; prepare_tx_message(31); break; #if defined(NEUTRAL_MONITOR_SUPPORT) case HOST_CMD_GET_READINGS_NEUTRAL: /* Exchange voltage, current and power readings (neutral). frequency, power factor and reactive power readings. */ tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; #if defined(SINGLE_PHASE) #if defined(VRMS_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->V_rms; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = 0; #endif #if defined(IRMS_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->neutral.I_rms; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = 0; #endif tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->neutral.power; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->neutral.power >> 16; #if REACTIVE_POWER_SUPPORT tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->reactive_power; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->reactive_power >> 16; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = 0; #endif #if VA_POWER_SUPPORT tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->VA_power; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = phase->VA_power >> 16; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = 0; #endif #if defined(POWER_FACTOR_SUPPORT) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = phase->power_factor; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = 0; #endif tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = phase->frequency; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = phase->V_dc_estimate; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = phase->V_dc_estimate >> 16; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 13] = phase->neutral.I_dc_estimate[0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 14] = phase->neutral.I_dc_estimate[0] >> 16; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 30] = 0; #else tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = neutral.I_rms; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = phase->frequency; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = 0; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 13] = phase->current.I_dc_estimate; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 14] = phase->current.I_dc_estimate >> 16; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 30] = 0; #endif prepare_tx_message(31); break; #endif case HOST_CMD_ERASE_FLASH_SEGMENT: /* Initialise flash data download, by erasing the area to be used, and setting the write pointer. */ /* There is no checking here to ensure we do not erase inappropriate places. */ next_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1]; flash_clr((int16_t *) next_flash_loc); tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; prepare_tx_message(2); break; case HOST_CMD_SET_FLASH_POINTER: next_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; prepare_tx_message(2); break; case HOST_CMD_FLASH_DOWNLOAD: if (is_calibration_enabled()) { next_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1]; for (i = 2; i < (rx_len - 12) >> 1; i++) flash_write_int16((int16_t *) next_flash_loc++, rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + i]); flash_secure(); /* Return the next address to the host, so it can check for missed messages */ tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = (uint16_t) next_flash_loc; prepare_tx_message(4); } break; case HOST_CMD_FLASH_UPLOAD: if (is_calibration_enabled()) { next_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; for (i = 1; i < MAX_IEC1107_MSG_BODY/2; i++) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + i] = *next_flash_loc++; prepare_tx_message(MAX_IEC1107_MSG_BODY); } break; case HOST_CMD_ZAP_MEMORY_AREA: /* Zap memory area (usually this will be flash) */ if (is_calibration_enabled()) { next_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1]; last_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 2]; while (next_flash_loc < last_flash_loc) flash_write_int16((int16_t *) next_flash_loc++, rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 3]); flash_secure(); tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = (uint16_t) next_flash_loc; prepare_tx_message(4); } break; case HOST_CMD_SUMCHECK_MEMORY: /* Sumcheck a specified memory area, and return the sumcheck */ if (is_calibration_enabled()) { next_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1]; last_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 2]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = 0; while (next_flash_loc < last_flash_loc) tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] += *next_flash_loc++; flash_secure(); prepare_tx_message(4); } break; case HOST_CMD_GET_RAW_POWER_PHASE_1: #if !defined(SINGLE_PHASE) case HOST_CMD_GET_RAW_POWER_PHASE_2: case HOST_CMD_GET_RAW_POWER_PHASE_3: phase = &chan[rx_msg->uint8[IEC1107_MSG_RX_START_BODY] - 0x91]; #endif tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->sample_count_logged; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->current.P_accum_logged[0][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->current.P_accum_logged[0][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->current.P_accum_logged[0][2]; #if GAIN_STAGES > 1 tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->current.P_accum_logged[1][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->current.P_accum_logged[1][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->current.P_accum_logged[1][2]; prepare_tx_message(16); #else prepare_tx_message(10); #endif break; #if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT) case HOST_CMD_GET_RAW_REACTIVE_POWER_PHASE_1: #if !defined(SINGLE_PHASE) case HOST_CMD_GET_RAW_REACTIVE_POWER_PHASE_2: case HOST_CMD_GET_RAW_REACTIVE_POWER_PHASE_3: phase = &chan[rx_msg->uint8[IEC1107_MSG_RX_START_BODY] - 0x95]; #endif tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->sample_count_logged; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->current.P_reactive_accum_logged[0][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->current.P_reactive_accum_logged[0][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->current.P_reactive_accum_logged[0][2]; #if GAIN_STAGES > 1 tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->current.P_reactive_accum_logged[1][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->current.P_reactive_accum_logged[1][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->current.P_reactive_accum_logged[1][2]; prepare_tx_message(16); #else prepare_tx_message(10); #endif break; #endif #if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT) case HOST_CMD_GET_RAW_POWER_NEUTRAL: tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->sample_count_logged; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->neutral.P_accum_logged[0][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->neutral.P_accum_logged[0][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->neutral.P_accum_logged[0][2]; #if GAIN_STAGES > 1 tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->neutral.P_accum_logged[1][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->neutral.P_accum_logged[1][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->neutral.P_accum_logged[1][2]; prepare_tx_message(16); #else prepare_tx_message(10); #endif break; #if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT) case HOST_CMD_GET_RAW_REACTIVE_POWER_NEUTRAL: tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->sample_count_logged; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->neutral.P_reactive_accum_logged[0][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->neutral.P_reactive_accum_logged[0][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->neutral.P_reactive_accum_logged[0][2]; #if GAIN_STAGES > 1 tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->neutral.P_reactive_accum_logged[0][0]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->neutral.P_reactive_accum_logged[0][1]; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->neutral.P_reactive_accum_logged[0][2]; prepare_tx_message(16); #else prepare_tx_message(10); #endif break; #endif #endif case HOST_CMD_CHECK_RTC_ERROR: tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; #if defined(__MSP430_HAS_TA3__) z = assess_rtc_speed(); #endif tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = z; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = z >> 16; prepare_tx_message(6); break; #if defined(CORRECTED_RTC_SUPPORT) case HOST_CMD_RTC_CORRECTION: tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = rtc_correction; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = rtc_correction >> 16; prepare_tx_message(6); break; #endif #if defined(MULTI_RATE_SUPPORT) case HOST_CMD_MULTIRATE_SET_PARAMETERS: i = multirate_put(&rx_msg->uint8[IEC1107_MSG_RX_START_BODY]); tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = i; prepare_tx_message(4); break; case HOST_CMD_MULTIRATE_GET_PARAMETERS: i = multirate_get(&rx_msg->uint8[IEC1107_MSG_RX_START_BODY], &tx_msg.uint8[IEC1107_MSG_TX_START_BODY]); prepare_tx_message(i); break; case HOST_CMD_MULTIRATE_CLEAR_USAGE: i = multirate_clear_usage(&rx_msg->uint8[IEC1107_MSG_RX_START_BODY]); tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80; tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = i; prepare_tx_message(4); break; case HOST_CMD_MULTIRATE_GET_USAGE: i = multirate_get_usage(&rx_msg->uint8[IEC1107_MSG_RX_START_BODY], &tx_msg.uint8[IEC1107_MSG_TX_START_BODY]); prepare_tx_message(i); break; #endif default: /* For all other message types reply with type 0xFF - bad message type */ tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY]; tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = 0xFF; prepare_tx_message(2); break; } } #endif #if defined(__MSP430__) && (defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT)) && (defined(USART0RX_VECTOR) || defined(USART0RX_ISR)) /* Interrupt to accept IEC1107 messages. */ ISR(USART0RX, serial_rx_interrupt0) { uint8_t ch; int i; int sum; ch = RXBUF0; if (char_timeout_1107 == 0) rx_msg_ptr = 0; char_timeout_1107 = SAMPLES_PER_10_SECONDS/200; if (rx_msg_ptr == 0) { if (ch == 0x68) { rx_msg.uint8[rx_msg_ptr++] = ch; rx_msg_len = 12 + MAX_IEC1107_MSG_BODY; } } else { if (rx_msg_ptr == 9) { if (ch <= MAX_IEC1107_MSG_BODY) rx_msg_len = 12 + ch; else rx_msg_ptr = 0; } rx_msg.uint8[rx_msg_ptr++] = ch; if (rx_msg_ptr == rx_msg_len) { /* End of message */ sum = rx_msg.uint8[0]; for (i = 1; i < rx_msg_len - 2; i++) sum += rx_msg.uint8[i]; if (rx_msg.uint8[rx_msg_len - 2] == (sum & 0xFF) && rx_msg.uint8[rx_msg_len - 1] == 0x16) { /* Good message received */ process_rx_message(&rx_msg, rx_msg_len); } rx_msg_ptr = 0; } } IFG2 &= ~URXIFG0; } #endif #if defined(__MSP430__) && (defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT)) && (defined(USART1RX_VECTOR) || defined(USART1RX_ISR)) /* Interrupt to accept IEC1107 messages. */ ISR(USART1RX, serial_rx_interrupt1) { uint8_t ch; int i; int sum; ch = RXBUF1; if (char_timeout_1107 == 0) rx_msg_ptr = 0; char_timeout_1107 = SAMPLES_PER_10_SECONDS/200; if (rx_msg_ptr == 0) { if (ch == 0x68) { rx_msg.uint8[rx_msg_ptr++] = ch; rx_msg_len = 12 + MAX_IEC1107_MSG_BODY; } } else { if (rx_msg_ptr == 9) { if (ch <= MAX_IEC1107_MSG_BODY) rx_msg_len = 12 + ch; else rx_msg_ptr = 0; } rx_msg.uint8[rx_msg_ptr++] = ch; if (rx_msg_ptr == rx_msg_len) { /* End of message */ sum = rx_msg.uint8[0]; for (i = 1; i < rx_msg_len - 2; i++) sum += rx_msg.uint8[i]; if (rx_msg.uint8[rx_msg_len - 2] == (sum & 0xFF) && rx_msg.uint8[rx_msg_len - 1] == 0x16) { /* Good message received */ process_rx_message(&rx_msg, rx_msg_len); } rx_msg_ptr = 0; } } } #endif /* Interrupt to send IEC1107 messages. */ #if defined(__MSP430__) && (defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT)) && (defined(USART0TX_VECTOR) || defined(USART0TX_ISR)) ISR(USART0TX, serial_tx_interrupt0) { TXBUF0 = tx_msg.uint8[tx_msg_ptr++]; if (tx_msg_ptr >= tx_msg_len) { /* Stop transmission */ U0IE &= ~UTXIE0; tx_msg_ptr = 0; tx_msg_len = 0; } } #endif #if defined(__MSP430__) && (defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT)) && (defined(USART1TX_VECTOR) || defined(USART1TX_ISR)) ISR(USART1TX, serial_tx_interrupt1) { TXBUF1 = tx_msg.uint8[tx_msg_ptr++]; if (tx_msg_ptr >= tx_msg_len) { /* Stop transmission */ IE2 &= ~UTXIE1; tx_msg_ptr = 0; tx_msg_len = 0; } } #endif