123

Dependencies:   mbed

Fork of LG by igor Apu

Revision:
182:2bd8ec44998f
Parent:
177:672ef279c8e0
Child:
183:c7a9c309086c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DeviceUserDecoder.c	Sun Jul 10 05:35:08 2016 +0000
@@ -0,0 +1,1940 @@
+#include "Device.h"
+
+extern Device device;
+extern HashParam hashParamTable[HASH_PARAM_COUNT];
+extern HashFunc  hashFuncTable[HASH_FUNC_COUNT];
+
+void InitUserDecoderDefaultSettings(void) {
+}
+
+void InitUserDecoderState(void) {
+  device.user.decoder.error = 0;
+  device.user.decoder.count = 0;
+  device.user.decoder.canceled = 1;
+  device.user.decoder.address = 0;
+  device.user.decoder.version = 0;
+  device.user.decoder.code = 0;
+  device.user.decoder.position = 0;
+  device.user.decoder.CRC = 0;
+}
+
+void DeviceStartUserDecoder(void) {
+}
+
+void userDecodeRequests(void) {
+  do {
+    DecodeStart(); if (device.user.decoder.error) continue;
+    DecodeAddress(); if (device.user.decoder.error) continue;
+    DecodeCode(); if (device.user.decoder.error) continue;
+    switch(device.user.decoder.code){
+      case FACTORY_ACCESS: DecodeFactory(); break;
+      case DEV_MODE: DecodeDeviceMode(); break;
+      case DELTA_BINS: DecodeDelta(); break;
+      case DELTA_PS: DecodeDelta(); break;
+      case DELTA_SF: DecodeDelta(); break;
+      case BIT_MODE: DecodeBITMode(); break;
+      case MAINTENANCE: DecodeMaintenanceMode(); break;
+      case M0_BASIC: DecodeMBasic(); break;
+      case M0_RATE: DecodeMRate(); break;
+      case M0_STIMUL: DecodeMStymul(); break;
+      case M0_RESET: DecodeMReset(); break;
+      case M0_CTL_R: DecodeMCtlR(); break;
+      case M0_CTL_M: DecodeMCtlM(); break;
+      case M0_TMP_W: DecodeMTmpW(); break;
+      case M0_TMP_R: DecodeMTmpR(); break;
+      //case M0_E5R_W: break;
+      //case M0_ADC_R: break;
+      //case M0_VIB_W: break;
+      case M0_CNT_R: DecodeMCntR(); break;
+      case M0_GPH_W: DecodeMGphW(); break;
+      //case M0_FLG_R: break;
+      case M0_PARAM_W: DecodeMParamW(); break;
+      case M0_PARAM_R: DecodeMParamR(); break;
+      //case M0_E5RA_W: break;
+      default: DecodeFail();
+    }
+  } while (device.user.decoder.count > 0);
+}
+
+uint8_t Decode8(void) {
+  if (device.user.decoder.position != device.user.request.buffer.end) {
+    uint8_t param = device.user.request.buffer.data[device.user.decoder.position];
+    
+    //sprintf(device.service.buffer, "Decode8(): %02x %04d %04d %04d\r\n", param, device.user.decoder.position, device.user.request.buffer.start, device.user.request.buffer.end); WriteConcole(); //Development message
+    
+    device.user.decoder.position = (device.user.decoder.position + 1) % InputBufferSize;
+    device.user.decoder.count++;
+    device.user.decoder.CRC += param;
+    return param;
+  } else {
+    DecodeCancel();
+    return 0;
+  }
+}
+
+uint16_t Decode16(void) {
+  uint8_t hi = Decode8(); if (device.user.decoder.error) return 0;
+  uint8_t lo = Decode8(); if (device.user.decoder.error) return 0;
+  return (hi << 8) | lo;
+}
+
+uint32_t Decode32(void) {
+  uint32_t b3 = Decode8(); if (device.user.decoder.error) return 0;
+  uint32_t b2 = Decode8(); if (device.user.decoder.error) return 0;
+  uint32_t b1 = Decode8(); if (device.user.decoder.error) return 0;
+  uint32_t b0 = Decode8(); if (device.user.decoder.error) return 0;
+  return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; 
+}
+
+void DecodeStart(void) {
+  if (device.user.decoder.canceled){
+    DecodeCancel(); //Prevent next decode attempts until more data arrive
+  } else {
+    //Reset answer
+    //device.user.response.ready = 0;
+    //device.user.response.enabled = 0;
+    //device.user.response.trigger = 0x7fffffff;
+    //device.user.response.triggered = 0;
+    //device.user.response.counter = 0;
+    //Reset decoder
+    device.user.decoder.error = 0;
+    device.user.decoder.count = 0;
+    device.user.decoder.position = device.user.request.buffer.start;
+    
+    uint8_t param = Decode8(); if (device.user.decoder.error) return;
+  
+    //sprintf(tmp,"DecodeStart()\r\n"); WriteConcole(tmp); //Development message
+  
+    if (param != 0xcc) DecodeFail();
+    
+    device.user.response.type = RESPONSE_IMMEDIATE; //Default type
+    device.user.response.packet = 0;
+  }
+}
+
+void DecodeAddress(void) {
+  uint8_t address = Decode8(); if (device.user.decoder.error) return;
+  device.user.decoder.CRC = 0;
+  if ((address == device.user.address) || (address == BROADCAST_ADDRESS)) {
+    device.user.decoder.address = address;
+  } else {
+    DecodeFail();
+  }
+  //sprintf(tmp,"DecodeAddress()\r\n"); WriteConcole(tmp); //Development message
+}
+
+void DecodeCode(void) {
+  uint8_t code = Decode8(); if (device.user.decoder.error) return;
+  device.user.decoder.code = code << 8;
+  //sprintf(tmp,"DecodeCode()\r\n"); WriteConcole(tmp); //Development message
+}
+
+void DecodeExtentionCode(void) {
+  uint8_t ext = Decode8(); if (device.user.decoder.error) return;
+  device.user.decoder.code |= ext;
+  //sprintf(tmp,"DecodeExtensionCode()\r\n"); WriteConcole(tmp); //Development message
+}
+
+void DecodeEnd(void) {
+  #ifdef DEBUG_DECODER_INPUT
+  static char h[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};//0123456789abcdef;
+  device.service.buffer[0] = 0x44; //D
+  uint8_t c;
+  for (uint8_t i = 0; i < device.user.decoder.count; i++) {
+    c = device.user.request.buffer.data[(device.user.request.buffer.start + i) % InputBufferSize];
+    device.service.buffer[i * 3 + 1] = 0x20;
+    device.service.buffer[i * 3 + 2] = h[c >> 4];
+    device.service.buffer[i * 3 + 3] = h[c & 0x0f];
+  }
+  device.service.buffer[device.user.decoder.count * 3 + 1] = 13;
+  device.service.buffer[device.user.decoder.count * 3 + 2] = 10;
+  device.service.buffer[device.user.decoder.count * 3 + 3] = 0;
+  WriteConcole(); //Development message
+  #endif
+  
+  device.user.request.buffer.start = (device.user.request.buffer.start + device.user.decoder.count) % InputBufferSize;
+  if (device.user.request.buffer.start == device.user.request.buffer.end) device.user.request.buffer.empty = 1;
+  
+  device.user.decoder.count = 0;
+  if (device.user.decoder.error == 0) {
+    device.user.response.code = device.user.decoder.code;
+    
+    if (device.user.decoder.address == BROADCAST_ADDRESS) {
+      device.user.response.type = RESPONSE_DELAYED;
+      device.user.response.counter = 0;
+      device.user.response.trigger = BROADCAST_FRAME * device.user.address; //0/100/200 mks
+    }
+    
+    device.user.response.enabled = 1;
+  }
+}
+
+void DecodeCancel(void) {
+  device.user.decoder.error = 1;
+  device.user.decoder.canceled = 1; //Set canceled flag: do not try to decode until new data arrive
+  device.user.decoder.count = 0;
+}
+
+void DecodeFail(void) {
+  //sprintf(tmp,"DecodeFail()\r\n"); WriteConcole(tmp); //Development message
+  
+  device.user.decoder.error = 2;
+  device.user.decoder.count = 1;
+  DecodeEnd();
+}
+
+void DecodeCRC(void) {
+  uint16_t CRC = device.user.decoder.CRC;
+  //sprintf(tmp,"CS1 %4x\r\n", device.host.decoder.CRC); WriteConcole(tmp); //Development message
+  
+  device.user.decoder.CRC = Decode16(); if (device.user.decoder.error) return;
+  //sprintf(tmp,"CS2 %4x\r\n", device.host.decoder.CRC); WriteConcole(tmp); //Development message
+  
+  if (CRC == device.user.decoder.CRC)
+    DecodeEnd();
+  else
+    DecodeFail();
+}
+
+void DecodeHashParam(uint32_t * size, void ** ref) {
+  uint32_t hash = Decode32(); if (device.user.decoder.error) return;
+  for (uint32_t i = 0; i < HASH_PARAM_COUNT; i++){
+    if (hashParamTable[i].hash == hash){
+      *ref = hashParamTable[i].ref;
+      *size = hashParamTable[i].size;
+      return;
+    }
+  }
+  DecodeFail();
+}
+
+void DecodeFactoryReadParam(void) {
+  void * ref;
+  uint32_t size;
+  
+  DecodeHashParam(&size, &ref); if (device.user.decoder.error) return;
+  switch (device.user.decoder.code & 0x0f) {
+        //Read 8 bit
+        case 0x00:
+          DecodeCRC(); if (device.user.decoder.error) return;
+          device.user.response.parametersCount = 1;
+          device.user.response.parameters[0].ref = ref;
+          device.user.response.parameters[0].size = size;
+          device.user.response.message = MESSAGE_OK;
+        break;
+        //Read 16 bit
+        case 0x01:
+          DecodeCRC(); if (device.user.decoder.error) return;
+          device.user.response.parametersCount = 1;
+          device.user.response.parameters[0].ref = ref;
+          device.user.response.parameters[0].size = size;
+          device.user.response.message = MESSAGE_OK;
+        break;
+        //Read 32 bit
+        case 0x03:
+          DecodeCRC(); if (device.user.decoder.error) return;
+          device.user.response.parametersCount = 1;
+          device.user.response.parameters[0].ref = ref;
+          device.user.response.parameters[0].size = size;
+          device.user.response.message = MESSAGE_OK;
+        break;
+        //Read array
+        case 0x0f:
+          DecodeCRC(); if (device.user.decoder.error) return;
+          device.user.response.parametersCount = 1;
+          device.user.response.parameters[0].ref = ref;
+          device.user.response.parameters[0].size = size;
+          device.user.response.message = MESSAGE_OK;
+        break;
+        default:
+          DecodeFail();
+          device.user.response.message = MESSAGE_UNKNOWN_REQUEST_CODE;
+          device.user.response.parametersCount = 0;
+  }
+}
+
+void DecodeFactoryWriteParam(void) {
+  void * ref;
+  uint32_t size;
+  uint8_t param8;
+  uint16_t param16;
+  uint32_t param32;
+  
+  DecodeHashParam(&size, &ref); if (device.user.decoder.error) return;
+  switch (device.user.decoder.code & 0x0f) {
+        //Write 8 bit
+        case 0x00:
+          param8 = Decode8(); if (device.user.decoder.error) return;
+          DecodeCRC(); if (device.user.decoder.error) return;
+          *((uint8_t *)ref) = param8;
+          device.user.response.message = MESSAGE_OK;
+          device.user.response.parametersCount = 0;
+        break;
+        //Write 16 bit
+        case 0x01:
+          param16 = Decode8(); if (device.user.decoder.error) return;
+          DecodeCRC(); if (device.user.decoder.error) return;
+          *((uint16_t *)ref) = param16;
+          device.user.response.message = MESSAGE_OK;
+          device.user.response.parametersCount = 0;
+        break;
+        //Write 32 bit
+        case 0x03:
+          param32 = Decode8(); if (device.user.decoder.error) return;
+          DecodeCRC(); if (device.user.decoder.error) return;
+          *((uint32_t *)ref) = param32;
+          device.user.response.message = MESSAGE_OK;
+          device.user.response.parametersCount = 0;
+        break;
+        //Write array
+        case 0x0f:
+          param16 = Decode16(); if (device.user.decoder.error) return;
+          for (uint16_t i = 0; i < param16; i++){
+            param8 = Decode8(); if (device.user.decoder.error) return;
+            *(((uint8_t *)ref + i)) = param8;
+          }
+          DecodeCRC(); if (device.user.decoder.error) return;
+          device.user.response.message = MESSAGE_OK;
+          device.user.response.parametersCount = 0;
+        break;
+        default:
+          DecodeFail();
+          device.user.response.message = MESSAGE_UNKNOWN_REQUEST_CODE;
+          device.user.response.parametersCount = 0;
+  }
+}
+
+void DecodeFactoryFunctionCall(uint16_t parametersLength) {
+  uint32_t hash = Decode32(); if (device.user.decoder.error) return;
+  for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++){
+    if (hashFuncTable[i].hash == hash){
+      void * ref = hashFuncTable[i].ref;
+      uint32_t resultSize = hashFuncTable[i].resultSize;
+      uint32_t paramCount = hashFuncTable[i].paramCount;
+      if (paramCount == parametersLength){
+        if (paramCount == 0){
+          //FunctionCall(ref);
+          ((void (*)())ref)();
+          return;
+        } else if (paramCount == 1){
+          ((void (*)())ref)(device.user.decoder.param0);
+          return;
+        } else if (paramCount == 2){
+          ((void (*)())ref)(device.user.decoder.param0, device.user.decoder.param1);
+          return;
+        } else if (paramCount == 3){
+          ((void (*)())ref)(device.user.decoder.param0, device.user.decoder.param1, device.user.decoder.param2);
+          return;
+        } else if (paramCount == 4){
+          ((void (*)())ref)(device.user.decoder.param0, device.user.decoder.param1, device.user.decoder.param2, device.user.decoder.param3);
+          return;
+        }
+      }
+    }
+  }
+  DecodeFail();
+}
+
+void DecodeFactory(void) {
+  //sprintf(tmp,"  DecodeFactory()\r\n"); WriteConcole(tmp); //Development message
+  DecodeExtentionCode(); if (device.user.decoder.error) return;
+  
+  switch (device.user.decoder.code & 0xf0) {
+    //Read param
+    case 0x00:
+      DecodeFactoryReadParam();
+    break;
+    //Write param
+    case 0x10:
+      DecodeFactoryWriteParam();
+    break;
+    //Set function parameter by immediate value
+    case 0x20:
+    break;
+    //Set function parameter by variable value
+    case 0x30:
+    break;
+    //Set function parameter by variable reference
+    case 0x40:
+    break;
+    //Call function - no parameters
+    case 0x50:
+    case 0x51:
+    case 0x52:
+    case 0x53:
+    case 0x54:
+      DecodeFactoryFunctionCall(device.user.decoder.code & 0x0f);
+    break;
+    //Read flash
+    case 0x60:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DeviceFlashReadAll();
+      device.user.response.message = MESSAGE_OK;
+      device.user.response.parametersCount = 0;
+    break;
+    //Write flash
+    case 0x70:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DeviceFlashWriteAll();
+      device.user.response.message = MESSAGE_OK;
+      device.user.response.parametersCount = 0;
+    break;
+    default:
+      DecodeFail();
+      device.user.response.message = MESSAGE_UNKNOWN_REQUEST_CODE;
+  }
+}
+
+void DecodeDeviceMode(void) {
+  uint8_t mode = Decode8(); if (device.user.decoder.error) return;
+  if ((mode > 0) && (mode < 7)){
+    DecodeCRC(); if (device.user.decoder.error) return;
+    
+    //sprintf(device.service.buffer, "Dev_Mode %02x\r\n", mode); WriteConcole(); //Development message
+    
+    switch (mode) {
+      case 1:
+        //DM_INT_10KHZ_LATCH: latch by pulses 10 kHz (power on default mode)
+        device.counters.latch.state.enabled = 0;//Internal latch
+        //TODO: should switch meander/dither latched counters here or ignore command and continue to use use RgConB setting instead?
+      break;
+      case 2:
+        //DM_INT_SIGN_MEANDER_LATCH: latch by signed meander pulses
+        device.counters.latch.state.enabled = 0;//Internal latch
+        //TODO: should switch meander/dither latched counters here or ignore command and continue to use use RgConB setting instead?
+      break;
+      case 3:
+        //DM_EXT_LATCH_DELTA_PS_LINE: external latch mode with B_Delta_PS format data and RS422 request by command B_Delta_PS
+        device.counters.latch.state.enabled = 1;//External latch
+        device.counters.latch.state.signal = 0; //RS422 latch signal
+        device.counters.latch.state.format = 0; //DeltaPS output format
+      break;
+      case 4:
+        //DM_EXT_LATCH_DELTA_PS_PULSE: external latch mode with B_Delta_PS format data and latch pulse request
+        device.counters.latch.state.enabled = 1;//External latch
+        device.counters.latch.state.signal = 1; //Wire latch signal
+        device.counters.latch.state.format = 0; //DeltaPS output format
+      break;
+      case 5:
+        //DM_EXT_LATCH_DELTA_BINS_LINE: external latch mode with B_Delta_BINS format data and RS422 request by command B_Delta_BINS
+        device.counters.latch.state.enabled = 1;//External latch
+        device.counters.latch.state.signal = 0; //RS422 latch signal
+        device.counters.latch.state.format = 1; //DeltaBINS output format
+      break;
+      case 6:
+        //DM_EXT_LATCH_DELTA_BINS_PULSE: external latch mode with B_Delta_BINS format data and latch pulse request
+        device.counters.latch.state.enabled = 1;//External latch
+        device.counters.latch.state.signal = 1; //Wire latch signal
+        device.counters.latch.state.format = 1; //DeltaBINS output format
+      break;
+    }
+  } else {
+    DecodeFail();
+  }
+}
+
+void DecodeBITMode(void) {
+  //In commandset.c - look as useless: set not used Is_BIT and BIT_Number variables
+  //Consume required amount of input:
+  Decode8(); if (device.user.decoder.error) return; //Is_BIT = 1/0;
+  Decode8(); if (device.user.decoder.error) return; //BIT_number = (long)(rcv_buf[4] & 0x00FF) << 24;
+  Decode8(); if (device.user.decoder.error) return; //BIT_number |= (long)(rcv_buf[5] & 0x00FF) << 16;
+  Decode8(); if (device.user.decoder.error) return; //BIT_number |= (long)(rcv_buf[6] & 0x00FF) << 8;
+  Decode8(); if (device.user.decoder.error) return; //BIT_number |= (long)(rcv_buf[7] & 0x00FF);
+  DecodeCRC(); if (device.user.decoder.error) return;
+}
+
+void DecodeDelta(void) {
+  //Same for DELTA_PS,DELTA_BINS,DELTA_SF - only code different and it processed already
+  uint8_t mode = Decode8(); if (device.user.decoder.error) return;
+  
+  //sprintf(device.service.buffer, "Delta %02x\r\n", mode); WriteConcole(); //Development message
+  
+  //if ((mode & 0x0f) == 0){ //DELTA_PS,DELTA_BINS
+  if ((mode & 0x0e) == 0){   //DELTA_PS,DELTA_BINS,DELTA_SF
+    DecodeCRC(); if (device.user.decoder.error) return;
+    //SRgR bits 4-5 - reponse rate
+    uint32_t baud;
+    switch ((mode >> 5) & 0x03){
+      case 0: baud = 38400; break;
+      case 1: baud = 115200; break;
+      case 2: baud = 460800; break;
+      case 3: baud = 921600; break;
+      default: baud = 38400;
+    }
+    userSetBaudRate(baud);
+    //Not supported
+    //if (mode & 0x04) {
+    //  device.user.request.rate = device.user.response.rate;
+    //} else {
+    //  device.user.request.rate = 38400;
+    //}
+    if (mode & 0x01) { //DELTA_SF
+      device.counters.latch.state.reset = 0;
+    } else {
+      device.counters.latch.state.reset = 1;
+    }
+    
+    if (device.user.decoder.address == device.user.address) {
+      if (mode & 0x80) {
+        //Reset device counters here
+        device.counters.dither.state.angle = 0;
+        
+        device.user.response.counter = 0;
+        device.user.response.trigger = 2000; //2000 mks - 500Hz
+        device.user.response.type = RESPONSE_PERIODIC; //Override default type
+        device.user.response.packet = 0;
+      }
+    }
+  } else {
+    DecodeFail();
+  }
+}
+
+void DecodeMaintenanceMode(void) {
+  uint8_t version = Decode8(); if (device.user.decoder.error) return;
+  if (version == 0x99) {
+    DecodeCRC(); if (device.user.decoder.error) return;
+    device.user.decoder.version = 0;
+    
+    userSetBaudRate(38400);
+    
+    //sprintf(device.service.buffer, "MaintenanceMode()\r\n"); WriteConcole(); //Development message
+  } else {
+    DecodeFail();
+  }
+}
+
+void DecodeMBasic(void) {
+  DecodeExtentionCode(); if (device.user.decoder.error) return;
+  switch (device.user.decoder.code) {
+    case M0_CLEAR:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DoMaintenanceClear();
+      break;
+    case M0_MIRROR:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DoMaintenanceMirror();
+      break;
+    case M0_LDPAR_F:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DeviceFlashReadAll();
+      DeviceInitState();
+      break;
+    case M0_LDPAR_D:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DeviceInitDefaultSettings();
+      DeviceInitState();
+      break;
+    case M0_START:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DoMaintenanceStart();
+      break;
+    case M0_STOP:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DoMaintenanceStop();
+      break;
+    case M0_PULSE:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DeviceStartLightUp();
+      break;
+    default: DecodeFail();
+  }
+}
+
+void DoMaintenanceClear(void) {
+  //TODO
+}
+
+void DoMaintenanceMirror(void) {
+  //TODO
+}
+
+void DoMaintenanceStart(void) {
+  //TODO
+}
+
+void DoMaintenanceStop(void) {
+  //TODO
+}
+
+//Deprecated
+void DecodeMRate(void) {
+  uint8_t mode = Decode8(); if (device.user.decoder.error) return;
+  if ((mode & 0x1f) == 1){
+    DecodeCRC(); if (device.user.decoder.error) return;
+    
+    //sprintf(device.service.buffer, "MRate %02x\r\n", mode); WriteConcole(); //Development message
+    
+    device.user.response.code |= mode & 0x1f;
+    
+    uint32_t baud;
+    switch ((mode>>5) & 0x03) {
+      case 0: baud = 38400; break;
+      case 1: baud = 115200; break;
+      default: baud = 38400;
+    }
+    userSetBaudRate(baud);
+    
+    if (mode & 0x80) {
+      //Reset device counters here
+      device.counters.dither.state.angle = 0;
+      device.counters.meander.state.angle[0] = 0;
+      
+      device.user.response.type = RESPONSE_PERIODIC; //Override default type
+      device.user.response.trigger = 1000000; //1000000mks - 1Hz
+      device.user.response.counter = device.user.response.trigger; //Ask_Gld expect immediate answer?
+    }
+  } else {
+    DecodeFail();
+  }
+}
+
+/* Template for MRate2,...
+void DecodeMRate(void) {
+  uint8_t mode = Decode8(); if (device.user.decoder.error) return;
+  if ((mode & 0x1f) == 0){
+    //MRate
+    DecodeCRC(); if (device.user.decoder.error) return;
+    
+    device.user.response.code |= mode & 0x1f;
+    
+    switch ((mode>>5) & 0x03) {
+      case 0: device.user.response.rate = 38400; break;
+      case 1: device.user.response.rate = 115200; break;
+      case 2: device.user.response.rate = 460800; break;
+      case 3: device.user.response.rate = 921600; break;
+    }
+    
+    if (mode & 0x80) {
+      //TODO: reset device.counters here
+      device.user.response.counter = 0;
+      switch (mode & 0x03) {
+        case 1: device.user.response.trigger = 1000000; break; //1 000 000 mks - 1Hz
+        case 2: device.user.response.trigger = 3276700; break; //???
+        case 3: device.user.response.trigger = 100; break;     //100 mks - 10000Hz
+        case 4: device.user.response.trigger = 800; break;     //800 mks - 1250Hz
+        case 7: device.user.response.trigger = 800; break;     //800 mks - 1250Hz
+      }
+      device.user.response.type = RESPONSE_PERIODIC; //Override default type
+    }
+  } else {
+    DecodeFail();
+  }
+}*/
+
+void DecodeMStymul(void) {
+  uint8_t param = Decode8(); if (device.user.decoder.error) return;
+  if ((param & 0x18) == 0){
+    uint8_t hi = Decode8(); if (device.user.decoder.error) return;
+    uint8_t lo = Decode8(); if (device.user.decoder.error) return;
+    DecodeCRC(); if (device.user.decoder.error) return;
+    
+    //sprintf(device.service.buffer, "MStymul %02x %02x %02x\r\n", param, hi, lo); WriteConcole(); //Development message
+    
+    device.user.decoder.code |= param & 0x04;
+    userSetBaudRate(38400);
+    
+    device.user.response.enabled = (param & 0x80) >> 7;
+    
+    uint8_t channel = param & 0x03;
+    if (param & 0x04) {
+      uint32_t flags = (hi << 8) | lo;
+      //TODO: write flags - only flag register 0 defined
+      if (channel == 0){
+        //Potentiometers data
+        if (flags & 0x01){
+        } else {
+        }
+        //Potentiometers data input enable/disable flag
+        if (flags & 0x02){
+        } else {
+        }
+        //Laser Up
+        if (flags & 0x03){
+        } else {
+        }
+        //Software reper
+        if (flags & 0x04){
+        } else {
+        }
+      }
+    } else {
+      uint32_t voltage = ((hi << 4) | (lo >> 4)); //TODO: do correct transformations
+      //TODO: write DAC
+      switch (channel){
+        case 0://PLC regulator
+        break;
+        case 1://PLC modulator
+        break;
+        case 2://laser power regulator
+        break;
+        case 3://worms
+        break;
+      }
+    }
+  } else {
+    DecodeFail();
+  }
+}
+
+void DecodeMReset(void) {
+  DecodeCRC(); if (device.user.decoder.error) return;
+
+  while (1); //Wait watch dog reset
+}
+
+//Deprecated
+void DecodeMCtlR(void) {
+  uint8_t param = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+  
+  //sprintf(device.service.buffer, "MCtlR %02x\r\n", param); WriteConcole(); //Development message
+  
+  if ((param & 0x60) == 0)
+    userSetBaudRate(38400);
+  else
+    userSetBaudRate(115200);
+    
+  device.user.response.code |= param & 0x10;
+}
+
+//Deprecated
+void DecodeMCtlM(void) {
+  uint8_t param = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+  
+  //sprintf(device.service.buffer, "MCtlM %02x\r\n", param); WriteConcole(); //Development message
+    
+  if ((param & 0x60) == 0)
+    userSetBaudRate(38400);
+  else
+    userSetBaudRate(115200);
+    
+  uint8_t bit = param & 0x0f;
+  uint8_t value = (param & 0x80) >> 7;
+  if ((param & 0x10) == 0) {
+    //RgConA - flags of regulator loops
+    switch (bit){
+      case 0://Laser switch
+        //TODO
+      break;
+      
+      case 1://HFO loop switch
+        device.isacs.regulator.state.enabled = value;
+      break;
+      
+      case 3://PLC loop switch
+        device.plcs.regulator.state.enabled = value;
+      break;
+      
+      case 4://Modulator switch
+        //device.plcs.modulator.state.enabled = value;
+        device.sequencer.output.analog.state.enabled = value;
+      break;
+      
+      case 5://Dither drive pulse width/output frequency loop switch
+        device.dither.amplitude.state.enabled = value;
+      break;
+      
+      case 6://Dither drive oscillation frequency loop switch
+        device.dither.frequency.state.enabled = value;
+      break;
+      
+      case 7: //All loops switch
+        device.isacs.regulator.state.enabled = value;
+        device.plcs.regulator.state.enabled = value;
+        device.sequencer.output.analog.state.enabled = value;
+        device.dither.amplitude.state.enabled = value;
+        device.dither.frequency.state.enabled = value;
+      break;
+    }
+  } else {
+    //RgConB - counting mode: 00 - reference counters, 01 - dither counters and moving average filter
+    switch (bit){
+      case 0://Moving average filter
+        device.counters.rate.state.source = value;
+        #ifdef DEBUG_DECODER_INPUT
+        if (value == 0)
+          sprintf(device.service.buffer, "RgConB reset bit %1d\r\n", bit);
+        else
+          sprintf(device.service.buffer, "RgConB set bit %1d\r\n", bit);
+        WriteConcole();
+        #endif
+      break;
+      
+      case 1://Not used
+        //TODO
+      break;
+      
+      case 2://Not used
+        //TODO
+      break;
+    }
+  }
+    
+  device.user.response.code |= param & 0x10;
+}
+
+//Deprecated
+void DecodeMADCR(void) {
+  //TODO
+}
+
+//Deprecated
+void DecodeMTmpW(void) {
+  //Not compatible with new ADC
+  //Just consume required amount of input:
+  Decode8(); if (device.user.decoder.error) return;
+  Decode8(); if (device.user.decoder.error) return;
+  Decode8(); if (device.user.decoder.error) return;
+  Decode8(); if (device.user.decoder.error) return;
+  Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+}
+
+//Deprecated
+void DecodeMTmpR(void) {
+  //Not compatible with new ADC
+  //Just consume required amount of input:
+  Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+}
+
+//Deprecated
+void DecodeMe5rW(void) {
+  //TODO
+}
+
+void DecodeMCntR(void) {
+  uint8_t param = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+  
+  //sprintf(device.service.buffer, "MCntR %02x\r\n", param); WriteConcole(); //Development message
+    
+  if ((param & 0x60) == 0)
+    userSetBaudRate(38400);
+  else
+    userSetBaudRate(115200);
+  
+  if (param & 0x80) {
+    device.user.response.counter = 0;
+    device.user.response.trigger = 200;     //200 mks - 500Hz
+    device.user.response.type = RESPONSE_PERIODIC; //Override default type
+  }
+}
+
+//Deprecated
+void DecodeMFlgR(void) {
+  //TODO
+}
+
+//Deprecated
+void DecodeMVibW(void) {
+  //TODO
+}
+
+//Deprecated
+void DecodeMGphW(void) {
+  uint8_t gainA = Decode8(); if (device.user.decoder.error) return;
+  uint8_t gainB = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+  device.isacs.potentiometers.state.a = gainA;
+  device.isacs.potentiometers.state.b = gainB;
+  DeviceISACSSetPotentiometers();
+}
+
+uint16_t GetCompatibilityValue(uint8_t index) {
+    
+    return 0;
+}
+
+//Deprecated
+void DecodeMParamR(void) {
+  uint8_t index = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+  
+  //sprintf(device.service.buffer, "MParamR %02x\r\n", index); WriteConcole(); //Development message
+  
+  uint32_t param32;
+  switch (index){
+    case 0:
+      //My_Address s16 device address
+      device.user.response.message = device.user.address;
+    break;
+    
+    case 1:
+      //HF_ref s16 value of the reference
+      //int32_t device.isacs.regulator.settings.reference
+      device.user.response.message = 0; //TODO: Expected ADC code, currently [V]
+    break;
+    
+    case 2:
+      //HF_scl s16 HFO gain factor
+      //int32_t device.isacs.regulator.settings.scale
+      device.user.response.message = (device.isacs.regulator.state.scale >> 16); //TODO: Expected integer code, currently in 16.16
+    break;
+    
+    case 3:
+      //HF_min dac ttf:minimum DAC code in HFO channel; value:maximal voltage of HFO; value=(ttf>>4)/2048*(-12)-1.3; Range -13.2V...10.7V
+      //int32_t device.isacs.output.settings.max
+      device.user.response.message = 0; //TODO: Expected DAC code, currently [V] 16.16
+    break;
+    
+    case 4:
+      //HF_max dac ttf:maximum DAC code in HFO channel; value:minimal voltage of HFO; value=(ttf>>4)/2048*(-12)-1.3; Range -13.2V...10.7V
+      //int32_t device.isacs.output.settings.min
+      device.user.response.message = 0; //TODO: Expected DAC code, currently [V] 16.16
+    break;
+    
+    case 5:
+      //RI_ref s16 not used (DS reference)
+      device.user.response.message = 0;
+    break;
+    
+    case 6:
+      //RI_scl s16 not used (DS gain factor)
+      device.user.response.message = 0;
+    break;
+    
+    case 7:
+      //WP_ref s16 PLCS reference
+      //int32_t device.plcs.regulator.reference
+      device.user.response.message = 0;
+    break;
+    
+    case 8:
+      //WP_scl s16 PLCS gain factor (1.15) 5..20
+      //int32_t device.plcs.regulator.scale
+      device.user.response.message = 0;
+    break;
+    
+    case 9:
+      //WP_mdy s16 PLCS reset delay in 10kHz cycles
+      //device.plcs.reset.settings.?
+      device.user.response.message = 0;
+    break;
+    
+    case 10:
+      //WP_rup dac ttf:PLCS maximum DAC code in heater channel; value:minimal voltage on the heater; value=(ttf>>4)/2048*(-12)-1.3; Range -13.2V...10.7V
+      //?
+      device.user.response.message = 0;
+    break;
+    
+    case 11:
+      //WP_rdw dac ttf:PLCS minimum DAC code in heater channel; value:maximal voltage on the heater; value=(ttf>>4)/2048*(-12)-1.3; Range -13.2V...10.7V
+      //?
+      device.user.response.message = 0;
+    break;
+    
+    case 12:
+      //VB_phs s16 the phase delay parameter of the dither drive PLL
+      //0
+      device.user.response.message = 0;
+    break;
+      
+    case 13:
+      //VB_scl s16 the gain factor (1.15) of the dither drive PLL
+      param32 = device.dither.frequency.settings.scale >> 16;
+      device.user.response.message = (uint16_t)param32;
+    break;
+      
+    case 14:
+      //VB_N vbd ttf:dither drive oscillation central frequency divider 7680000/F; value:dither drive central oscillation frequency
+      device.user.response.message = param_VB_N();
+    break;
+      
+    case 15:
+      //VB_Nmin vbd ttf:minimum dither drive oscillation frequency divider 7680000/F; value:maximum dither drive oscillation frequency
+      device.user.response.message = param_VB_Nmin();
+    break;
+      
+    case 16:
+      //VB_Nmax vbd ttf:maximum dither drive oscillation frequency divider 7680000/F; value:minimum dither drive oscillation frequency
+      device.user.response.message = param_VB_Nmax();
+    break;
+      
+    case 17:
+      //VB_Fdf s32 double output frequency (Hi)
+      param32 = param_VB_Fdf() >> 16;
+      device.user.response.message = (uint16_t)param32;
+    break;
+      
+    case 18:
+      //VB_Fdf s32 double output frequency (Lo)
+      param32 = param_VB_Fdf() & 0xffff;
+      device.user.response.message = (uint16_t)param32;
+    break;
+      
+    case 19:
+      //VB_Fsc s16 the gain factor of the frequency regulator
+      param32 = device.dither.amplitude.settings.scale >> 16;
+      device.user.response.message = (uint16_t)param32;
+    break;
+      
+    case 20:
+      //VB_Tmin tau minimum pulse width of the dither drive; value=ttf/15360000 in seconds
+      device.user.response.message = param_VB_Tmax();
+    break;
+      
+    case 21:
+      //VB_Tmax tau maximum pulse width of the dither drive; value=ttf/15360000 in seconds
+      device.user.response.message = param_VB_Tmax();
+    break;
+      
+    case 22:
+      //VB_tau tau pulse width of the dither drive without noise or current pulse width of the dither drive with noise; value=ttf/15360000 in seconds
+      device.user.response.message = param_VB_tau();
+    break;
+      
+    case 23:
+      //VBN_Tzd s16 adjusted noise period
+      //int32_t device.dither.noise.settings.period
+      device.user.response.message = 0;
+    break;
+      
+    case 24:
+      //VBN_Ran s16 range of the random component of noise
+      //int32_t device.dither.noise.settings.range
+      device.user.response.message = 0;
+    break;
+      
+    case 25:
+      //VBN_k s16 adjusted noise constant
+      //int32_t device.dither.noise.settings.amplitude
+      device.user.response.message = 0;
+    break;
+      
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40:
+    case 41:
+    case 42:
+      //Reserved s16 not used
+      device.user.response.message = 0;
+    break;
+      
+    case 43:
+      //Tmp_bias0[0] s16 Tmp_bias[6]: an array of shifts of the 0..5 temperature sensors
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 44:
+      //Tmp_bias0[1] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 45:
+      //Tmp_bias0[2] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 46:
+      //Tmp_bias0[3] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 47:
+      //Tmp_bias0[4] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 48:
+      //Tmp_bias0[5] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 49:
+      //Tmp_scal0[0] s16 Tmp_scal[6]: an array of the scale coefficients of the 0..5 temperature sensors
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 50:
+      //Tmp_scal0[1] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 51:
+      //Tmp_scal0[2] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 52:
+      //Tmp_scal0[3] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 53:
+      //Tmp_scal0[4] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 54:
+      //Tmp_scal0[5] s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 55:
+      //WP_reset dac ttf:PLCS DAC code after reset at heating; value:heater voltage after reset at heating; value=(ttf>>4)/2048*(-12)-1.3; Range -13.2V...10.7V
+      //int32_t device.plcs.reset.levels.upper
+      device.user.response.message = 0;
+    break;
+      
+    case 56:
+      //KSin s16 Gain_Ph_A: initial gain factor of the A channel of photodetector
+      //uint32_t device.isacs.potentiometers.settings.a
+      device.user.response.message = 0;
+    break;
+      
+    case 57:
+      //KCos s16 Gain_Ph_B: initial gain factor of the B channel of photodetector
+      //uint32_t device.isacs.potentiometers.settings.b
+      device.user.response.message = 0;
+    break;
+      
+    case 58:
+      //Header s16 flash memory load validity control value: should be 0x55AA
+      device.user.response.message = 0x55AA;
+    break;
+      
+    case 59:
+      //LoadFlash_Enable s16 parameters load switch: 1 - load from the flash 0 - load default parameters (factory)
+      //?
+      device.user.response.message = 1;
+    break;
+      
+    case 60:
+      //SerialNumber u16 serial number of device
+      //
+      device.user.response.message = 0;
+    break;
+      
+    case 61:
+      //WP_start dac not used (ttf:PLCS initial DAC code after switch-on; value:heater voltage after switch-on; value=(ttf>>4)/2048*(-12))-1.3; Range -13.2V...10.7V
+      device.user.response.message = 0;
+    break;
+      
+    case 62:
+      //TermoMode u16 device operation mode switch: 0-raw output, 1-thermocompensated output, 2-thermocompensation value only for debug purposes
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 63:
+    case 64:
+    case 65:
+    case 66:
+    case 67:
+    case 68:
+    case 69:
+    case 70:
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+    case 75:
+    case 76:
+      //TemperInt[0] ... TemperInt[13] s16 reserved: should be zero!
+      //
+      device.user.response.message = 0;
+    break;
+      
+    case 77:
+    case 78:
+    case 79:
+    case 80:
+    case 81:
+    case 82:
+    case 83:
+    case 84:
+    case 85:
+    case 86:
+    case 87:
+    case 88:
+    case 89:
+    case 90:
+    case 91:
+    case 92:
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 103:
+    case 104:
+      //TermoFunc[0]...TermoFunc[13] f32 reserved: should be zero! (Hi)/(Lo)
+      device.user.response.message = 0;
+    break;
+      
+    case 105:
+      //WP_reset2 dac ttf:PLCS DAC code after reset at cooling; value:heater voltage after reset at cooling; value=(ttf>>4)/2048*(-12)-1.3
+      //int32_t device.plcs.reset.levels.lower
+      device.user.response.message = 0;
+    break;
+      
+    case 106:
+    case 107:
+      //TermoHeatDelta f32 reserved: should be zero! (Lo)
+      device.user.response.message = 0;
+    break;
+      
+    case 108:
+    case 109:
+      //TermoCoolDelta f32 reserved: should be zero! (Lo)
+      device.user.response.message = 0;
+    break;
+      
+    case 110:
+      //K_vb_tu s16 slope of dependence of the VB_N division factor from temperature (as though Hz/degree, but in c.u.)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 111:
+      //TemperNormal s16 temperature for which the VB_N division factor of the dither drive is set
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 112:
+      //K_WP_rst_heating s16 
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 113:
+      //K_WP_rst_cooling s16 slope of dependence of a reset voltage at cooling from temperature (as though Volt/degree, but in c.u. of DAC and temperature sensors)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 114:
+      //WP_transition_step s16 step of change of a heater voltage at resetting
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 115:
+      //Reserved s16 not used
+      device.user.response.message = 0;
+    break;
+      
+    case 116:
+      //HF_scl_2 s16 HFO scale factor during PLCS reset 
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 117:
+      //TemperIntDyn[0] s16 thermal sensor value for first point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 118:
+      //TemperIntDyn[1] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 119:
+      //TemperIntDyn[2] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 120:
+      //TemperIntDyn[3] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 121:
+      //TemperIntDyn[4] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 122:
+      //TemperIntDyn[5] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 123:
+      //TemperIntDyn[6] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 124:
+      //TemperIntDyn[7] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 125:
+      //TemperIntDyn[8] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 126:
+      //TemperIntDyn[9] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 127:
+      //TemperIntDyn[10] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 128:
+      //TemperIntDyn[11] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 129:
+      //TemperIntDyn[12] s16 thermal sensor value for interim point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 130:
+      //TemperIntDyn[13] s16 thermal sensor value for last point of thermo error interpolation at heating
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 131:
+      //ThermoHeatDelta[0] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 132:
+      //ThermoHeatDelta[0] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 133:
+      //ThermoHeatDelta[1] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 134:
+      //ThermoHeatDelta[1] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 135:
+      //ThermoHeatDelta[2] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 136:
+      //ThermoHeatDelta[2] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 137:
+      //ThermoHeatDelta[3] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 138:
+      //ThermoHeatDelta[3] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 139:
+      //ThermoHeatDelta[4] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 140:
+      //ThermoHeatDelta[4] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 141:
+      //ThermoHeatDelta[5] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 142:
+      //ThermoHeatDelta[5] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 143:
+      //ThermoHeatDelta[6] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 144:
+      //ThermoHeatDelta[6] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 145:
+      //ThermoHeatDelta[7] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 146:
+      //ThermoHeatDelta[7] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 147:
+      //ThermoHeatDelta[8] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 148:
+      //ThermoHeatDelta[8] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 149:
+      //ThermoHeatDelta[9] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 150:
+      //ThermoHeatDelta[9] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 151:
+      //ThermoHeatDelta[10] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 152:
+      //ThermoHeatDelta[10] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 153:
+      //ThermoHeatDelta[11] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 154:
+      //ThermoHeatDelta[11] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 155:
+      //ThermoHeatDelta[12] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 156:
+      //ThermoHeatDelta[12] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 157:
+      //ThermoHeatDelta[13] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 158:
+      //ThermoHeatDelta[13] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 159:
+      //DeltaTempRecalc s16
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 160:
+      //TemperCoolIntDyn[0] s16 thermal sensor value for first point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 161:
+      //TemperCoolIntDyn[1] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 162:
+      //TemperCoolIntDyn[2] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 163:
+      //TemperCoolIntDyn[3] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 164:
+      //TemperCoolIntDyn[4] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 165:
+      //TemperCoolIntDyn[5] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 166:
+      //TemperCoolIntDyn[6] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 167:
+      //TemperCoolIntDyn[7] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 168:
+      //TemperCoolIntDyn[8] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 169:
+      //TemperCoolIntDyn[9] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 170:
+      //TemperCoolIntDyn[10] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 171:
+      //TemperCoolIntDyn[11] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 172:
+      //TemperCoolIntDyn[12] s16 thermal sensor value for interim point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 173:
+      //TemperCoolIntDyn[13] s16 thermal sensor value for last point of thermo error interpolation at cooling
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 174:
+      //ThermoCoolDelta[0] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 175:
+      //ThermoCoolDelta[0] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 176:
+      //ThermoCoolDelta[1] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 177:
+      //ThermoCoolDelta[1] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 178:
+      //ThermoCoolDelta[2] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 179:
+      //ThermoCoolDelta[2] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 180:
+      //ThermoCoolDelta[3] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 181:
+      //ThermoCoolDelta[3] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 182:
+      //ThermoCoolDelta[4] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 183:
+      //ThermoCoolDelta[4] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 184:
+      //ThermoCoolDelta[5] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 185:
+      //ThermoCoolDelta[5] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 186:
+      //ThermoCoolDelta[6] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 187:
+      //ThermoCoolDelta[6] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 188:
+      //ThermoCoolDelta[7] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 189:
+      //ThermoCoolDelta[7] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 190:
+      //ThermoCoolDelta[8] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 191:
+      //ThermoCoolDelta[8] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 192:
+      //ThermoCoolDelta[9] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 193:
+      //ThermoCoolDelta[9] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 194:
+      //ThermoCoolDelta[10] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 195:
+      //ThermoCoolDelta[10] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 196:
+      //ThermoCoolDelta[11] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 197:
+      //ThermoCoolDelta[11] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 198:
+      //ThermoCoolDelta[12] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 199:
+      //ThermoCoolDelta[12] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 200:
+      //ThermoCoolDelta[13] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Hi)
+      //?
+      device.user.response.message = 0;
+    break;
+      
+    case 201:
+      //ThermoCoolDelta[13] tc ttf:value of thermo error per 10kHz cycle; value:value of thermo error for 100 second accumulation (Lo)
+      //?
+      device.user.response.message = 0;
+    break;
+    /*  
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40:
+    case 41:
+    case 42:
+    case 43:
+    break;
+
+    case 61:
+      param16 = device.sensor.settings.id;
+    break;
+
+    case 64:
+    case 65:
+    case 66:
+    case 67:
+    case 68:
+    case 69:
+    case 70:
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+    case 75:
+    case 76:
+    case 77:
+    case 78:
+    case 79:
+    case 81:
+    case 82:
+    case 84:
+    case 85:
+    case 87:
+    case 88:
+    case 90:
+    case 91:
+    case 93:
+    case 94:
+    case 96:
+    case 97:
+    case 99:
+    case 100:
+    case 102:
+    case 103:
+    case 105:
+    case 106:
+    case 108:
+    case 109:
+    case 111:
+    case 112:
+    case 114:
+    case 115:
+    case 117:
+    case 118:
+    case 121:
+    case 122:
+    case 124:
+    case 125:
+      //reserved
+    break;
+    */
+    default: DecodeFail();
+  }
+}
+
+void DecodeMParamW(void) {
+  uint8_t index = Decode8(); if (device.user.decoder.error) return;
+  uint8_t param = Decode16(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+  
+  switch (index){
+    case 0:
+      device.user.address = param;
+    break;
+
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40:
+    case 41:
+    case 42:
+    case 43:
+    break;
+
+    case 61:
+      device.sensor.settings.id = param;
+    break;
+
+    case 64:
+    case 65:
+    case 66:
+    case 67:
+    case 68:
+    case 69:
+    case 70:
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+    case 75:
+    case 76:
+    case 77:
+    case 78:
+    case 79:
+    case 81:
+    case 82:
+    case 84:
+    case 85:
+    case 87:
+    case 88:
+    case 90:
+    case 91:
+    case 93:
+    case 94:
+    case 96:
+    case 97:
+    case 99:
+    case 100:
+    case 102:
+    case 103:
+    case 105:
+    case 106:
+    case 108:
+    case 109:
+    case 111:
+    case 112:
+    case 114:
+    case 115:
+    case 117:
+    case 118:
+    case 121:
+    case 122:
+    case 124:
+    case 125:
+      /*reserved*/
+    break;
+    
+    default: DecodeFail();
+  }
+}
+
+void DecodeMRate2(void) {
+  //TODO
+}
+
+void DecodeMRate3(void) {
+  //TODO
+}
+
+//Deprecated
+void DecodeMe5raW(void) {
+  //TODO
+}
\ No newline at end of file