lark1s_demo/lark1s/lark1s.c
2024-07-13 22:57:08 +08:00

539 lines
17 KiB
C

#include "lark1s.h"
/* information register */
#define LARK1S_REG_SN (0x0004)
#define LARK1S_SIZE_SN (8)
#define LARK1S_REG_GAS3_INFO (0x0300)
#define LARK1S_SIZE_GAS3_INFO (42)
#define LARK1S_REG_GAS3_CALI_DATA (0x032A)
#define LARK1S_SIZE_GAS3_CALI_DATA (24)
/* data register */
#define LARK1S_REG_DATA (0x0500)
#define LARK1S_SIZE_DATA (52)
/* writable register */
#define LARK1S_REG_GAS3_CALI_ZERO_RECORD (0x1012)
#define LARK1S_REG_GAS3_CALI_SPAN_RECORD (0x1028)
#define LARK1S_REG_GAS3_CALI_ACTIVE (0x103E)
#define LARK1S_REG_GAS3_CALI_RESTORE (0x1042)
/* status register */
#define LARK1S_REG_STATUS (0x0600)
#define LARK1S_SIZE_STATUS (11)
#define MODBUS_FUNCTION_CODE_READ_INPUT (0x04)
#define MODBUS_FUNCTION_CODE_WRITE_SINGLE (0x06)
#define MODBUS_FUNCTION_CODE_WRITE_MULTI (0x10)
#define MB_GET_HWORD(p) (uint16_t)((((uint8_t*)p)[0] << 8) | ((uint8_t*)p)[1])
#define MB_GET_UWORD(p) (uint32_t)((((uint8_t*)p)[0] << 24) | (((uint8_t*)p)[1] << 16) | (((uint8_t*)p)[2] << 8) | ((uint8_t*)p)[3])
#define MB_GET_SWORD(p) (int32_t)((((uint8_t*)p)[0] << 24) | (((uint8_t*)p)[1] << 16) | (((uint8_t*)p)[2] << 8) | ((uint8_t*)p)[3])
static volatile uint8_t mb_addr = 0x01;
static volatile uint16_t mb_errno = 0x00;
struct crc16_result_s {
uint8_t crch;
uint8_t crcl;
};
static const uint8_t crc_tabl[] = { //CRC low Value Table
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40,
};
static const uint8_t crc_tabh[] = { //CRC high Value Table
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40,
};
/* polynomial: x16+x15+x2+x1 */
static void crc16_8005_calc(uint8_t *p, uint16_t len, struct crc16_result_s *ret)
{
struct crc16_result_s crc = {0xFF, 0xFF};
uint8_t i, index;
for (i = 0; i < len; i++) {
index = crc.crcl ^ p[i];
crc.crcl = crc.crch ^ crc_tabl[index];
crc.crch = crc_tabh[index];
}
ret->crcl = crc.crcl;
ret->crch = crc.crch;
}
static int lark1s_frame_check(uint8_t *p, uint16_t len)
{
struct crc16_result_s crc;
if (p[0] != mb_addr) {
return LARK1S_PARSE_MB_ADDR_NOT_MATCH;
}
crc16_8005_calc(p, len - 2, &crc);
if (crc.crcl != p[len - 2] || crc.crch != p[len - 1]) {
return LARK1S_PARSE_CRC_ERROR;
}
return LARK1S_PARSE_OK;
}
void lark1s_set_mb_address(uint8_t address)
{
mb_addr = address;
}
uint16_t lark1s_get_mb_errno(void)
{
return mb_errno;
}
int lark1s_req_sn(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_SN >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_SN & 0xFF;
buffer[i++] = (LARK1S_SIZE_SN >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_SN & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_sn(uint8_t *buffer, int length, char *sn)
{
int ret;
int i = 0;
if (length != LARK1S_SIZE_SN * 2 + 5) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_SN * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
for (int j = 0; j < LARK1S_SIZE_SN * 2; j++) {
sn[j] = buffer[i++];
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_info(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_GAS3_INFO >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_GAS3_INFO & 0xFF;
buffer[i++] = (LARK1S_SIZE_GAS3_INFO >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_GAS3_INFO & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_gas3_info(uint8_t *buffer, int length, struct lark1s_gas_info_s *info)
{
int ret;
int i = 0;
if (length != LARK1S_SIZE_GAS3_INFO * 2 + 5) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_GAS3_INFO * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
info->gas_id = MB_GET_UWORD(buffer + i);
for (int j = 0; j < 12; j++) {
info->gas_name[j] = buffer[i + 4 + j];
}
info->unit_id = MB_GET_UWORD(buffer + i + 16);
for (int j = 0; j < 8; j++) {
info->unit_name[j] = buffer[i + 20 + j];
}
info->range = MB_GET_UWORD(buffer + i + 32);
info->min_cali = MB_GET_UWORD(buffer + i + 76);
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_data(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_GAS3_CALI_DATA >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_GAS3_CALI_DATA & 0xFF;
buffer[i++] = (LARK1S_SIZE_GAS3_CALI_DATA >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_GAS3_CALI_DATA & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_gas3_cali_data(uint8_t *buffer, int length, struct lark1s_gas_cali_data_s *data)
{
int ret;
int i = 0;
if (length != LARK1S_SIZE_GAS3_CALI_DATA * 2 + 5) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_GAS3_CALI_DATA * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
data->available = MB_GET_UWORD(buffer + i);
data->zero_sig_cts = MB_GET_UWORD(buffer + i + 4);
data->zero_ref_cts = MB_GET_UWORD(buffer + i + 8);
data->zero_det_temp = MB_GET_UWORD(buffer + i + 12);
data->zero_lamp_temp = MB_GET_UWORD(buffer + i + 16);
data->span_concentration = MB_GET_UWORD(buffer + i + 28);
data->span_sig_cts = MB_GET_UWORD(buffer + i + 32);
data->span_ref_cts = MB_GET_UWORD(buffer + i + 36);
data->span_det_temp = MB_GET_UWORD(buffer + i + 40);
data->span_lamp_temp = MB_GET_UWORD(buffer + i + 44);
return LARK1S_PARSE_OK;
}
int lark1s_req_data(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_DATA >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_DATA & 0xFF;
buffer[i++] = (LARK1S_SIZE_DATA >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_DATA & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_data(uint8_t *buffer, int length, struct lark1s_data_s *data)
{
int ret;
int i = 0;
if (length != LARK1S_SIZE_DATA * 2 + 5) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_DATA * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
data->det_temp = MB_GET_UWORD(buffer + i);
data->air_pressure = MB_GET_UWORD(buffer + i + 8);
data->cts_ref = MB_GET_UWORD(buffer + i + 36);
data->gas3_reading = MB_GET_UWORD(buffer + i + 64);
data->cts_gas3 = MB_GET_UWORD(buffer + i + 68);
data->gas3_compensated_reading = MB_GET_SWORD(buffer + i + 104);
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_zero_record(uint8_t *buffer, uint16_t type)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_WRITE_SINGLE;
buffer[i++] = (LARK1S_REG_GAS3_CALI_ZERO_RECORD >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_GAS3_CALI_ZERO_RECORD & 0xFF;
buffer[i++] = (type >> 8) & 0xFF;
buffer[i++] = type & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_gas3_cali_zero_record(uint8_t *buffer, int length)
{
int ret;
int i = 0;
if (length != 8) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_WRITE_SINGLE) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if(LARK1S_REG_GAS3_CALI_ZERO_RECORD != MB_GET_HWORD(buffer + i)) {
return LARK1S_PARSE_CALI_REG_ERROR;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_span_record(uint8_t *buffer, uint32_t concentration)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_WRITE_MULTI;
buffer[i++] = (LARK1S_REG_GAS3_CALI_SPAN_RECORD >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_GAS3_CALI_SPAN_RECORD & 0xFF;
buffer[i++] = 0;
buffer[i++] = 2; /* register number */
buffer[i++] = 4; /* data byte number */
buffer[i++] = (concentration >> 24) & 0xFF;
buffer[i++] = (concentration >> 16) & 0xFF;
buffer[i++] = (concentration >> 8) & 0xFF;
buffer[i++] = concentration & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_gas3_cali_span_record(uint8_t *buffer, int length)
{
int ret;
int i = 0;
if (length != 8) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_WRITE_MULTI) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if(LARK1S_REG_GAS3_CALI_SPAN_RECORD != MB_GET_HWORD(buffer + i)) {
return LARK1S_PARSE_CALI_REG_ERROR;
}
if(2 != MB_GET_HWORD(buffer + i + 2)) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_active(uint8_t *buffer, uint16_t type)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_WRITE_SINGLE;
buffer[i++] = (LARK1S_REG_GAS3_CALI_ACTIVE >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_GAS3_CALI_ACTIVE & 0xFF;
buffer[i++] = (type >> 8) & 0xFF;
buffer[i++] = type & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_gas3_cali_active(uint8_t *buffer, int length)
{
int ret;
int i = 0;
if (length != 8) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_WRITE_SINGLE) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if(LARK1S_REG_GAS3_CALI_ACTIVE != MB_GET_HWORD(buffer + i)) {
return LARK1S_PARSE_CALI_REG_ERROR;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_restore(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_WRITE_SINGLE;
buffer[i++] = (LARK1S_REG_GAS3_CALI_RESTORE >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_GAS3_CALI_RESTORE & 0xFF;
buffer[i++] = 0x00;
buffer[i++] = 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_gas3_cali_restore(uint8_t *buffer, int length)
{
int ret;
int i = 0;
if (length != 8) {
return LARK1S_PARSE_FRAME_ERROR;
}
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_WRITE_SINGLE) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if(LARK1S_REG_GAS3_CALI_RESTORE != MB_GET_HWORD(buffer + i)) {
return LARK1S_PARSE_CALI_REG_ERROR;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_status(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_STATUS >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_STATUS & 0xFF;
buffer[i++] = (LARK1S_SIZE_STATUS >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_STATUS & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_status(uint8_t *buffer, int length, struct lark1s_status_s *status)
{
int ret;
int i = 0;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_STATUS * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
status->zero_record[0] = MB_GET_HWORD(buffer + i + 0);
status->zero_record[1] = MB_GET_HWORD(buffer + i + 2);
status->zero_record[2] = MB_GET_HWORD(buffer + i + 4);
status->zero_record[3] = MB_GET_HWORD(buffer + i + 6);
status->span_record[0] = MB_GET_HWORD(buffer + i + 8);
status->span_record[1] = MB_GET_HWORD(buffer + i + 10);
status->span_record[2] = MB_GET_HWORD(buffer + i + 12);
status->span_record[3] = MB_GET_HWORD(buffer + i + 14);
status->active = MB_GET_HWORD(buffer + i + 16);
status->restore = MB_GET_HWORD(buffer + i + 18);
return LARK1S_PARSE_OK;
}