123

Dependencies:   mbed

Fork of LG by igor Apu

Revision:
161:efd949e8d536
Child:
166:c3c0b8a90d81
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DeviceUserProtocolDecoder.c	Sun May 15 19:12:12 2016 +0000
@@ -0,0 +1,923 @@
+#include "Device.h"
+
+extern Device device;
+extern HashParam hashParamTable[HASH_PARAM_COUNT];
+extern HashFunc  hashFuncTable[HASH_FUNC_COUNT];
+
+void InitUserProtocolDecoder(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 DeviceDecodeUserRequests(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_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: 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 {
+    device.user.decoder.error = 0;
+    device.user.decoder.count = 0;
+    device.user.decoder.position = device.user.request.buffer.start;
+    device.user.response.enabled = 0;
+    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
+  }
+}
+
+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) {
+  //sprintf(tmp,"DecodeEnd()\r\n"); WriteConcole(tmp); //Development message
+  
+  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) {
+  /*
+        *** Description ***
+        Elio5_cmd_en.pdf:
+        Device_Mode - device operating modes:
+        The device operating mode is encoded by 4 low bits (0..3) of byte 4.
+          0 – reserved;
+          1 – internal latch mode: latch by pulses 10 kHz (power on default mode);
+          2 - internal latch mode: latch by signed meander pulses;
+          3 – external latch mode with B_Delta_PS format data and RS422 request by command B_Delta_PS;
+          4 – external latch mode with B_Delta_PS format data and latch pulse request;
+          5 – external latch mode with B_Delta_BINS format data and RS422 request by command B_Delta_BINS;
+          6 – external latch mode with B_Delta_BINS format data and latch pulse request;
+    
+        *** Command action ***
+        commandset_asm.asm - exec_CMD:
+        CMD_Mode = 3;
+          
+        commandset.c - B_Dev_Mode(void):
+        Device_Mode = rcv_buf[3] & 0x00ff; //e. read the byte of command parameter from the receiver buffer and write it to the counter mode register  //r. и записываем в регистр режима счетчиков
+        trm_cycl = 0;                      //e. periodic data transmission is not needed //r. периодическая передача ответа не требуется
+  
+        commandset_asm.asm - Mk_AskDev():
+        num_of_par = 2;                //e. 2 parameters output //r. выводить два параметра
+        addr_param[0] = &Device_Mode;  //e. address of the counter mode register (intenal latch, external latch, etc.) //r. адрес регистра режима счетчиков (внутр., внешняя защелка и т.д.)
+        addr_param[1] = &SRgR;         //e. address of the mode register of the processor card //r. адрес регистра режима платы процессора
+        size_param[0] = 2;             //e. size of the counter mode register - 2 bytes //r. размер регистра режима счетчиков - 2 байта
+        size_param[1] = 2;             //e. size of the mode register of the processor card //r. размер регистра режима платы процессора
+        trm_cycl = 0;                  //e. forbid cyclic transmission of the parameter //r. запретить передачу параметра в цикле
+        trm_ena = 1;                   //e. allow operation of the transmitter //r. разрешить работу передатчика
+      */
+  uint8_t mode = Decode8(); if (device.user.decoder.error) return;
+  if ((mode > 0) && (mode < 7)){
+    DecodeCRC(); if (device.user.decoder.error) return;
+    switch (mode) {
+      case 1: device.latch.mode = DeviceLatch10kHz; break;
+      case 2: device.latch.mode = DeviceLatchMeander; break;
+      case 3: device.latch.mode = DeviceLatchRS422; device.latch.format = DeviceLatchFormatDeltaPS; break;
+      case 4: device.latch.mode = DeviceLatchPin;   device.latch.format = DeviceLatchFormatDeltaPS; break;
+      case 5: device.latch.mode = DeviceLatchRS422; device.latch.format = DeviceLatchFormatDeltaBINS; break;
+      case 6: device.latch.mode = DeviceLatchPin;   device.latch.format = DeviceLatchFormatDeltaBINS; break;
+    }
+    //device.host.response.type = RESPONSE_IMMEDIATE; //Default type
+  } 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;
+  //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
+    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 & 0x04) {
+      device.user.request.rate = device.user.response.rate;
+    } else {
+      device.user.request.rate = 38400;
+    }
+    if (mode & 0x01) { //DELTA_SF
+      device.latch.reset = 0;
+    } else {
+      device.latch.reset = 1;
+    }
+    //device.latch.mode = DeviceLatchRS422; //Have to set by Device Mode command?
+    if (device.user.response.code == DELTA_PS) device.latch.format = DeviceLatchFormatDeltaPS;
+    else if (device.user.response.code == DELTA_BINS) device.latch.format = DeviceLatchFormatDeltaBINS;
+    else if (device.user.response.code == DELTA_SF) device.latch.format = DeviceLatchFormatDeltaSF;
+    //TODO: Latch(); //Remember counters for transmission, reset counters
+    if (device.user.decoder.address == device.user.address) {
+      if (mode & 0x80) {
+        //TODO: reset device.counters here (or already done in Latch())
+        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;
+  } 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();
+      break;
+    case M0_LDPAR_D:
+      DecodeCRC(); if (device.user.decoder.error) return;
+      DeviceInitAllWithDefaults();
+      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
+}
+
+void DecodeMRate(void) {
+  uint8_t mode = Decode8(); if (device.user.decoder.error) return;
+  if ((mode && 0x18) == 0){
+    DecodeCRC(); if (device.user.decoder.error) return;
+    
+    device.user.response.code |= mode & 0x07;
+    
+    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;
+    
+    device.user.decoder.code |= param & 0x04;
+    device.user.response.rate = 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
+}
+
+void DecodeMControlRead(void) {
+  uint8_t param = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+    
+  if (param & 60 == 0)
+    device.user.response.rate = 38400;
+  else
+    device.user.response.rate = 115200;
+    
+  device.user.response.code |= param & 0x10;
+}
+
+void DecodeMControlWrite(void) {
+  uint8_t param = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+    
+  if (param & 60 == 0)
+    device.user.response.rate = 38400;
+  else
+    device.user.response.rate = 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;
+      break;
+      
+      case 5://Dither drive pulse width/output frequency loop switch
+        device.dither.carrier.state.enabled = value;
+      break;
+      
+      case 6://Dither drive oscillation frequency loop switch
+        device.dither.oscillation.state.enabled = value;
+      break;
+      
+      case 7: //All loops switch
+        device.isacs.regulator.state.enabled = value;
+        device.plcs.regulator.state.enabled = value;
+        device.plcs.modulator.state.enabled = value;
+        device.dither.carrier.state.enabled = value;
+        device.dither.oscillation.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
+        //TODO
+      break;
+      
+      case 1://
+        //TODO
+      break;
+      
+      case 2://
+        //TODO
+      break;
+    }
+  }
+    
+  device.user.response.code |= param & 0x10;
+}
+
+void DecodeMADCR(void) {
+  //TODO
+}
+
+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;
+}
+
+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;
+}
+
+void DecodeMe5rW(void) {
+  //TODO
+}
+
+void DecodeMCntR(void) {
+  //TODO
+}
+
+void DecodeMFlgR(void) {
+  //TODO
+}
+
+void DecodeMVibW(void) {
+  //TODO
+}
+
+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;
+}
+
+void DecodeMParamR(void) {
+  //TODO
+  uint8_t index = Decode8(); if (device.user.decoder.error) return;
+  DecodeCRC(); if (device.user.decoder.error) return;
+  
+  uint16_t param16;
+  switch (index){
+    case 0:
+      param16 = device.user.address;
+    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
+}
+
+void DecodeMe5raW(void) {
+  //TODO
+}
\ No newline at end of file