SP8EBC-ParaTNC/system/src/umb_master/umb_0x23_offline_data.c

193 wiersze
4.7 KiB
C

/*
* umb_0x23_offline_data.c
*
* Created on: 20.03.2020
* Author: mateusz
*/
#include "../umb_master/umb_master.h"
#include "../umb_master/umb_0x23_offline_data.h"
#include "config_data.h"
#include "rte_wx.h"
#include "main.h"
#define UNSIGNED_CHAR 0x10
#define SIGNED_CHAR 0x11
#define UNSIGNED_SHORT 0x12
#define SIGNED_SHORT 0x13
#define UNSIGNED_LONG 0x14
#define SIGNED_LONG 0x15
#define FLOAT 0x16
#define UNSIGNED_CHAR_LN 1
#define SIGNED_CHAR_LN 1
#define UNSIGNED_SHORT_LN 2
#define SIGNED_SHORT_LN 2
#define UNSIGNED_LONG_LN 4
#define SIGNED_LONG_LN 4
#define FLOAT_LN 4
umb_retval_t umb_0x23_offline_data_request(umb_frame_t* frame, umb_context_t* ctx, uint16_t channel_number) {
if (ctx->state != UMB_STATUS_IDLE && ctx->state != UMB_STATUS_ERROR) {
return UMB_BUSY;
}
frame->command_id = 0x23;
frame->slave_class = (uint8_t)(config_data_umb.slave_class & 0xFF);
frame->slave_id = (uint8_t)(config_data_umb.slave_id & 0xFF);
frame->lenght = 2;
// channels are little endian 16 bit unsigned integer
frame->payload[0] = channel_number & 0xFF;
frame->payload[1] = (channel_number & 0xFF00) >> 8;
ctx->state = UMB_STATUS_READY_TO_SEND;
ctx->current_routine = 0x23;
return UMB_OK;
}
umb_retval_t umb_0x23_offline_data_callback(umb_frame_t* frame, umb_context_t* ctx) {
// return value
umb_retval_t output = UMB_OK;
// status from sensor
uint8_t status = frame->payload[0];
// value type
uint8_t type = 0;
// channel from response
uint16_t channel = 0;
// raw value from sensor
uint32_t raw_value = 0;
// signed value to be written in RTE
int32_t value_for_rte = 0;
// temporary float point buffer to handle this type
float temp = 0.0f;
// fetch the channel number
channel = frame->payload[1] | (frame->payload[2] << 8);
// check if status is OK
if (status == 0x00) {
// fetch the value type
type = frame->payload[3];
// fetch the raw value into temporary storage
switch (type) {
case UNSIGNED_CHAR:
case SIGNED_CHAR: {
raw_value = frame->payload[4];
break;
}
case UNSIGNED_SHORT:
case SIGNED_SHORT: {
raw_value = frame->payload[4] | (frame->payload[5] << 8);
break;
}
case UNSIGNED_LONG:
case SIGNED_LONG: {
raw_value = frame->payload[4] | (frame->payload[5] << 8) | (frame->payload[6] << 16) | (frame->payload[7] << 24);
break;
}
case FLOAT: {
raw_value = frame->payload[4] | (frame->payload[5] << 8) | (frame->payload[6] << 16) | (frame->payload[7] << 24);
break;
}
default: {
ctx->state = UMB_STATUS_ERROR;
output = UMB_GENERAL_ERROR;
return output;
}
}
// convert a raw value to a value to be stored in the rte as an integer multiplicity of .1
switch (type) {
case UNSIGNED_CHAR:
case UNSIGNED_SHORT:
case UNSIGNED_LONG:
case SIGNED_LONG: {
// multiply this by the factor of ten
value_for_rte = raw_value * 10;
break;
}
// for signed types do a conversion to intermediate signed variable to take care about
// negative numbers
case SIGNED_CHAR: {
value_for_rte = (int32_t)(((int8_t)(raw_value & 0xFF)) * 10);
break;
}
case SIGNED_SHORT: {
value_for_rte = (int32_t)(((int16_t)(raw_value & 0xFFFF)) * 10);
break;
}
case FLOAT: {
temp = *(float*)&raw_value;
value_for_rte = (int32_t)(temp * 10.0f);
break;
}
// there is no default case here as if a type was any different from supported the function would
// quit before, in previous switch
}
// limit the value as rte stores only 16 bit signed integers
if (value_for_rte > 32767) {
ctx->state = UMB_STATUS_ERROR;
return UMB_VALUE_OUT_OF_RANGE;
}
else if (value_for_rte < (int32_t)-32767) {
ctx->state = UMB_STATUS_ERROR;
return UMB_VALUE_OUT_OF_RANGE;
}
for (int i = 0; i < UMB_CHANNELS_STORAGE_CAPAC; i++) {
// look for free slot in channel values storage
if( rte_wx_umb_channel_values[i][0] == (int16_t)0xFFFF ||
rte_wx_umb_channel_values[i][0] == (int16_t)channel )
{
// if found store the value and then break the loop execution
rte_wx_umb_channel_values[i][0] = channel;
rte_wx_umb_channel_values[i][1] = (int16_t)value_for_rte;
break;
}
}
}
else {
// if not stop further processing
ctx->state = UMB_STATUS_ERROR;
ctx->last_fault_channel = channel;
// copy current error code to the buffer
ctx->nok_error_codes[ctx->nok_error_it] = status;
// move the iterator through the buffer
ctx->nok_error_it++;
// check if and end of the buffer is reach here
ctx->nok_error_it %= UMB_CONTEXT_ERR_HISTORY_LN;
// trigger the status frame
ctx->trigger_status_msg = 1;
ctx->time_of_last_nok = main_get_master_time();
output = UMB_NOK_STATUS_GOT_WITH_RESP;
}
return output;
}