123

Dependencies:   mbed

Fork of LG by igor Apu

DeviceUserProtocolDecoder.c

Committer:
Diletant
Date:
2016-06-19
Revision:
173:7f938afb0447
Parent:
167:bedc0a9d559a
Child:
177:672ef279c8e0

File content as of revision 173:7f938afb0447:

#include "Device.h"

extern Device device;
extern HashParam hashParamTable[HASH_PARAM_COUNT];
extern HashFunc  hashFuncTable[HASH_FUNC_COUNT];

void InitUserProtocolDecoderDefaultSettings(void) {
}

void InitUserProtocolDecoderState(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 DeviceStartUserProtocolDecoder(void) {
}

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();
      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
}

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;
        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
        //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
}