Example #1
0
unsigned char parseCmd(void) {
  unsigned char txed = 0;
  //mode_word.s_full = 0;

  switch (rx_ptr->d0) {

    case OPC_FCLK:
      // fast clock:
      FastClock.mins     = rx_ptr->d1;
      FastClock.hours    = rx_ptr->d2;
      FastClock.wday     = rx_ptr->d3 & 0x0F;
      FastClock.mon      = (rx_ptr->d3 & 0xF0) >> 4;
      FastClock.div      = rx_ptr->d4;
      FastClock.mday     = rx_ptr->d5;
      FastClock.temp     = rx_ptr->d6;
      FastClock.issync   = TRUE;
      FastClock.synctime = 0;
      FastClock.gotfirstsync = TRUE;
      break;

    case OPC_QNN:
      canmsg.opc  = OPC_PNN;
      canmsg.d[0] = (NN_temp / 256) & 0xFF;
      canmsg.d[1] = (NN_temp % 256) & 0xFF;
      canmsg.d[2] = params[0];
      canmsg.d[3] = params[2];
      canmsg.d[4] = NV1;
      canmsg.len = 5;
      canQueue(&canmsg);
      //LED2 = 1;
      txed = 1;
      break;

    case OPC_RQNPN:
      // Request to read a parameter
      if (thisNN() == 1) {
        doRqnpn((unsigned int) rx_ptr->d3);
      }
      break;

    case OPC_SNN:
    {
      if( Wait4NN ) {
        unsigned char nnH = rx_ptr->d1;
        unsigned char nnL = rx_ptr->d2;
        NN_temp = nnH * 256 + nnL;
        eeWrite(EE_NN, nnH);
        eeWrite(EE_NN+1, nnL);
        Wait4NN = 0;
        canmsg.b[d0] = OPC_NNACK;
        canmsg.b[d1] = nnH / 256;
        canmsg.b[d2] = nnL % 256;
        canmsg.b[dlc] = 3;
        canbusSend(&canmsg);
      }
      break;
    }


    case OPC_RQNP:
      if( Wait4NN ) {
        canmsg.opc = OPC_PARAMS;
        canmsg.d[0] = params[0];
        canmsg.d[1] = params[1];
        canmsg.d[2] = params[2];
        canmsg.d[3] = params[3];
        canmsg.d[4] = params[4];
        canmsg.d[5] = params[5];
        canmsg.d[6] = params[6];
        canmsg.len = 7;
        canQueue(&canmsg);
        txed = 1;
      }
      break;

    case OPC_RTOF:
      break;

    case OPC_NVRD:
      if( thisNN() ) {
        byte nvnr = rx_ptr->d3;
        if( nvnr == 1 ) {
          canmsg.opc = OPC_NVANS;
          canmsg.d[0] = (NN_temp / 256) & 0xFF;
          canmsg.d[1] = (NN_temp % 256) & 0xFF;
          canmsg.d[2] = nvnr;
          canmsg.d[3] = NV1;
          canmsg.len = 4;
          canQueue(&canmsg);
          txed = 1;
        }
        else if( nvnr == 2 ) {
          canmsg.opc = OPC_NVANS;
          canmsg.d[0] = (NN_temp / 256) & 0xFF;
          canmsg.d[1] = (NN_temp % 256) & 0xFF;
          canmsg.d[2] = nvnr;
          canmsg.d[3] = CANID;
          canmsg.len = 4;
          canQueue(&canmsg);
          txed = 1;
        }
      }
      break;

    case OPC_NVSET:
      if( thisNN() ) {
        byte nvnr = rx_ptr->d3;
        if( nvnr == 1 ) {
          NV1 = rx_ptr->d4;
          eeWrite(EE_NV, NV1);
          dim_timer = NV1 & CFG_DISPDIM;
          if( dim_timer == 0 )
            dim_timer++;
          date_enabled = (NV1 & CFG_SHOWDATE) ? TRUE:FALSE;
          pos_display = (NV1 & CFG_POSDISPLAY) ? TRUE:FALSE;
          temp_enabled = (NV1 & CFG_SHOWTEMP) ? TRUE:FALSE;
        }
        else if( nvnr == 2 ) {
          CANID = rx_ptr->d4;
          eeWrite(EE_CANID, CANID);
        }
      }
      break;

    default: break;
  }

    rx_ptr->con = 0;
    if (can_bus_off) {
      // At least one buffer is now free
      can_bus_off = 0;
      PIE3bits.FIFOWMIE = 1;
    }

    return txed;
}
Example #2
0
unsigned char parseCmd(CANMsg *cmsg) {
  unsigned char txed = 0;
  CANMsg canmsg;
  //mode_word.s_full = 0;

  if (!(NV1 & CFG_READONLY)) {
    send2LocoNet(cmsg);
  }

  switch (cmsg->b[d0]) {

    case OPC_ASRQ:
    {
      addr = cmsg->b[d3] * 256 + cmsg->b[d4];
      if (SOD == addr && doSOD == 0) {
        ioIdx = 0;
        doSOD = 1;
      }
      break;
    }

    case OPC_WLNID:
      LNModule.id = cmsg->b[d1] * 256 + cmsg->b[d2];
      LNModule.addr = cmsg->b[d3] * 256 + cmsg->b[d4];
      if (LNModule.id > 9999)
        LNModule.id /= 10;
      break;

    case OPC_QLNID:
      canmsg.b[d0] = OPC_PLNID;
      canmsg.b[d1] = LNModule.id / 256;
      canmsg.b[d2] = LNModule.id % 256;
      canmsg.b[d3] = LNModule.addr / 256;
      canmsg.b[d4] = LNModule.addr % 256;
      canmsg.b[dlc] = 5;
      canbusSendExt(&canmsg);
      break;

    case OPC_QNN:
      canmsg.b[d0] = OPC_PNN;
      canmsg.b[d1] = (NN_temp / 256) & 0xFF;
      canmsg.b[d2] = NN_temp & 0xFF;
      canmsg.b[d3] = params[0];
      canmsg.b[d4] = params[2];
      canmsg.b[d5] = NV1;
      canmsg.b[dlc] = 6;
      canbusSend(&canmsg);
      txed = 1;
      break;

    case OPC_RQNPN:
      // Request to read a parameter
      if (thisNN(cmsg) == 1) {
        doRqnpn((unsigned int) cmsg->b[d3]);
      }
      break;

    case OPC_SNN:
    {
      if (Wait4NN) {
        nnH = cmsg->b[d1];
        nnL = cmsg->b[d2];
        NN_temp = nnH * 256 + nnL;
        eeWriteShort(EE_NN, NN_temp);
        Wait4NN = 0;
      }
      break;
    }


    case OPC_RQNP:
      if (Wait4NN) {
        canmsg.b[d0] = OPC_PARAMS;
        canmsg.b[d1] = params[0];
        canmsg.b[d2] = params[1];
        canmsg.b[d3] = params[2];
        canmsg.b[d4] = params[3];
        canmsg.b[d5] = params[4];
        canmsg.b[d6] = params[5];
        canmsg.b[d7] = params[6];
        canmsg.b[dlc] = 8;
        canbusSend(&canmsg);
        txed = 1;
      }
      break;

    case OPC_BOOT:
      // Enter bootloader mode if NN matches
      if (thisNN(cmsg) == 1) {
        doSwSave = TRUE;
        while (doSwSave) SaveSwState();
        eeWrite(EE_BOOT, 0xFF);
        Reset();
      }
      break;


    case OPC_NVRD:
      if (thisNN(cmsg)) {
        byte nvnr = cmsg->b[d3];
        if (nvnr == 1) {
          canmsg.b[d0] = OPC_NVANS;
          canmsg.b[d1] = (NN_temp / 256) & 0xFF;
          canmsg.b[d2] = NN_temp & 0xFF;
          canmsg.b[d3] = nvnr;
          canmsg.b[d4] = NV1;
          canmsg.b[dlc] = 5;
          canbusSend(&canmsg);
          txed = 1;
        } else if (nvnr == 2) {
          canmsg.b[d0] = OPC_NVANS;
          canmsg.b[d1] = (NN_temp / 256) & 0xFF;
          canmsg.b[d2] = NN_temp & 0xFF;
          canmsg.b[d3] = nvnr;
          canmsg.b[d4] = CANID;
          canmsg.b[dlc] = 5;
          canbusSend(&canmsg);
          txed = 1;
        }

      }
      break;

    case OPC_NVSET:
      if (thisNN(cmsg)) {
        byte nvnr = cmsg->b[d3];
        if (nvnr == 1) {
          NV1 = cmsg->b[d4];
          eeWrite(EE_NV, NV1);
        } else if (nvnr == 2) {
          CANID = cmsg->b[d4];
          eeWrite(EE_CANID, CANID);
        }
      }
      break;


    case OPC_NNLRN:
      if (thisNN(cmsg)) {
        isLearning = TRUE;
      }
      break;

    case OPC_NNULN:
      if (thisNN(cmsg)) {
        isLearning = FALSE;
        LED6_FLIM = PORT_OFF;
      }
      break;

    case OPC_EVLRN:
      if (isLearning) {
        nn = cmsg->b[d1] * 256 + cmsg->b[d2];
        addr = cmsg->b[d3] * 256 + cmsg->b[d4];
        idx = cmsg->b[d5];
        var = cmsg->b[d6];

        if (idx == 0) {
          SOD = addr;
          eeWriteShort(EE_SOD, addr);
        } else if (idx == 1) {
          SWStart = addr;
          eeWriteShort(EE_SWSTART, addr);
        } else if (idx == 2) {
          SWEnd = addr;
          eeWriteShort(EE_SWEND, addr);
        } else if (idx == 3) {
          FBStart = addr;
          eeWriteShort(EE_FBSTART, addr);
        } else if (idx == 4) {
          FBEnd = addr;
          eeWriteShort(EE_FBEND, addr);
        }
      }
      break;

    case OPC_NERD:
      if (thisNN(cmsg)) {
        doEV = 1;
        evIdx = 0;
      }
      break;

    default:
      break;
  }

  return txed;
}
Example #3
0
File: commands.c Project: AndTH/GCA
unsigned char parseCmd(CANMsg *cmsg) {
    unsigned char txed = 0;
    //mode_word.s_full = 0;
    switch (cmsg->b[d0]) {

        case OPC_ASRQ:
        {
            int addr = cmsg->b[d3] * 256 + cmsg->b[d4];
            if (SOD == addr && doSOD == 0) {
                ioIdx = 0;
                doSOD = 1;
            }
            break;
        }

        case OPC_ACON:
        case OPC_ASON:
        {
            ushort nn = cmsg->b[d1] * 256 + cmsg->b[d2];
            ushort addr = cmsg->b[d3] * 256 + cmsg->b[d4];
            setOutput(nn, addr, 1);
            break;
        }

        case OPC_ACOF:
        case OPC_ASOF:
        {
            ushort nn = cmsg->b[d1] * 256 + cmsg->b[d2];
            ushort addr = cmsg->b[d3] * 256 + cmsg->b[d4];
            setOutput(nn, addr, 0);
            break;
        }

        case OPC_RQNPN:
            // Request to read a parameter
            if (thisNN(cmsg) == 1) {
                doRqnpn((unsigned int) cmsg->b[d3]);
            }
            break;

        case OPC_SNN:
        {
            if (Wait4NN) {
                unsigned char nnH = cmsg->b[d1];
                unsigned char nnL = cmsg->b[d2];
                NN_temp = nnH * 256 + nnL;
                eeWrite(EE_NN, nnH);
                eeWrite(EE_NN + 1, nnL);
                Wait4NN = 0;
                LED2 = 0;
            }
            break;
        }

        case OPC_RQNP:
            if (Wait4NN) {
                CANMsg canmsg;
                canmsg.b[d0] = OPC_PARAMS;
                canmsg.b[d1] = params[0];
                canmsg.b[d2] = params[1];
                canmsg.b[d3] = params[2];
                canmsg.b[d4] = params[3];
                canmsg.b[d5] = params[4];
                canmsg.b[d6] = params[5];
                canmsg.b[d7] = params[6];
                canmsg.b[dlc] = 8;
                canbusSend(&canmsg);
                txed = 1;
            }
            break;

        case OPC_BOOT:
            // Enter bootloader mode if NN matches
            if (thisNN(cmsg) == 1) {
                eeWrite((unsigned char) (&bootflag), 0xFF);
                Reset();
            }
            break;

        case OPC_RTOF:
            if (NV1 & CFG_SAVEOUTPUT) {
                saveOutputStates();
            }
            break;

        case OPC_NNCLR:
            if (thisNN(cmsg) && isLearning) {
                setupIO(TRUE);
            }
            break;

        case OPC_QNN:
        {
            CANMsg canmsg;
            canmsg.b[d0] = OPC_PNN;
            canmsg.b[d1] = (NN_temp / 256) & 0xFF;
            canmsg.b[d2] = (NN_temp % 256) & 0xFF;
            canmsg.b[d3] = params[0];
            canmsg.b[d4] = params[2];
            canmsg.b[d5] = NV1;
            canmsg.b[dlc] = 6;
            canbusSend(&canmsg);
        }
            //LED2 = 1;
            txed = 1;
            break;

        case OPC_RTON:
            pnnCount = 0;
            /*
            setOutput(0,  9, (pnnCount & 0x01) ? 1:0);
            setOutput(0, 10, (pnnCount & 0x02) ? 1:0);
            setOutput(0, 11, (pnnCount & 0x04) ? 1:0);
            setOutput(0, 12, (pnnCount & 0x08) ? 1:0);
            setOutput(0, 13, (pnnCount & 0x10) ? 1:0);
            setOutput(0, 14, (pnnCount & 0x20) ? 1:0);
            setOutput(0, 15, (pnnCount & 0x40) ? 1:0);
            setOutput(0, 16, (pnnCount & 0x80) ? 1:0);
             */
            break;

        case OPC_PNN:
            pnnCount++;
            /*
            setOutput(0,  9, (pnnCount & 0x01) ? 1:0);
            setOutput(0, 10, (pnnCount & 0x02) ? 1:0);
            setOutput(0, 11, (pnnCount & 0x04) ? 1:0);
            setOutput(0, 12, (pnnCount & 0x08) ? 1:0);
            setOutput(0, 13, (pnnCount & 0x10) ? 1:0);
            setOutput(0, 14, (pnnCount & 0x20) ? 1:0);
            setOutput(0, 15, (pnnCount & 0x40) ? 1:0);
            setOutput(0, 16, (pnnCount & 0x80) ? 1:0);
             */
            break;

        case OPC_NVRD:
            if (thisNN(cmsg)) {
                CANMsg canmsg;
                byte nvnr = cmsg->b[d3];
                if (nvnr == 1) {
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = (NN_temp % 256) & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = NV1;
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                } else if (nvnr < 18) {
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = (NN_temp % 256) & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = Ports[nvnr - 2].cfg;
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                } else if (nvnr == 18) {
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = (NN_temp % 256) & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = getPortStates(0); // port status 1-8
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                } else if (nvnr == 19) {
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = (NN_temp % 256) & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = getPortStates(1); // port status 9-16
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                } else if (nvnr == 20) {
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = (NN_temp % 256) & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = CANID;
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                }
            }
            break;

        case OPC_NVSET:
            if (thisNN(cmsg)) {
                byte nvnr = cmsg->b[d3];
                if (nvnr == 1) {
                    NV1 = cmsg->b[d4];
                    eeWrite(EE_NV, NV1);
                } else if (nvnr < 18) {
                    Ports[nvnr - 2].cfg = cmsg->b[d4];
                    eeWrite(EE_PORTCFG + (nvnr - 2), Ports[nvnr - 2].cfg);
                    configPort(nvnr - 2);
                } else if (nvnr == 20) {
                    CANID = cmsg->b[d4];
                    eeWrite(EE_CANID, CANID);
                }

            }
            break;

        case OPC_NNLRN:
            if (thisNN(cmsg)) {
                isLearning = TRUE;
            }
            break;

        case OPC_NNULN:
            if (thisNN(cmsg)) {
                isLearning = FALSE;
                LED2 = PORT_OFF;
            }
            break;

        case OPC_EVLRN:
            if (isLearning) {
                ushort evtnn = cmsg->b[d1] * 256 + cmsg->b[d2];
                ushort addr = cmsg->b[d3] * 256 + cmsg->b[d4];
                byte idx = cmsg->b[d5];
                byte val = cmsg->b[d6];
                if (idx < 16) {
                    Ports[idx].evtnn = evtnn;
                    Ports[idx].addr = addr;
                    eeWriteShort(EE_PORTNN + (2 * idx), evtnn);
                    eeWriteShort(EE_PORTADDR + (2 * idx), addr);
                }
                if (idx == 16) {
                    SOD = addr;
                    eeWrite(EE_SOD, addr / 256);
                    eeWrite(EE_SOD + 1, addr % 256);
                }
            }
            break;

        case OPC_NERD:
            if (thisNN(cmsg)) {
                doEV = 1;
                evIdx = 0;
                // start of day event
                {
                    CANMsg canmsg;
                    canmsg.b[d0] = OPC_ENRSP;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = (NN_temp % 256) & 0xFF;
                    canmsg.b[d3] = 0;
                    canmsg.b[d4] = 0;
                    canmsg.b[d5] = SOD / 256;
                    canmsg.b[d6] = SOD % 256;
                    canmsg.b[d7] = 16;
                    canmsg.b[dlc] = 8;
                    canbusSend(&canmsg);
                }
                txed = 1;
            }
            break;


        default: break;
    }
    return txed;
}
Example #4
0
unsigned char parseCmd(CANMsg *cmsg) {
    unsigned char txed = 0;
    //mode_word.s_full = 0;

    switch (cmsg->b[d0]) {

        case OPC_ASRQ:
        {
            addr = cmsg->b[d3] * 256 + cmsg->b[d4];
            if (SOD == addr && doSOD == 0) {
                ioIdx = 0;
                doSOD = 1;
            }
            break;
        }

        case OPC_ACON:
        case OPC_ASON:
        {
            nn = cmsg->b[d1] * 256 + cmsg->b[d2];
            addr = cmsg->b[d3] * 256 + cmsg->b[d4];
            setOutput(nn, addr, 1);
            break;
        }

        case OPC_ACOF:
        case OPC_ASOF:
        {
            nn = cmsg->b[d1] * 256 + cmsg->b[d2];
            addr = cmsg->b[d3] * 256 + cmsg->b[d4];
            setOutput(nn, addr, 0);
            break;
        }

        case OPC_BOOT:
            // Enter bootloader mode if NN matches
            if (thisNN(cmsg) == 1) {
                eeWrite((unsigned char) (&bootflag), 0xFF);
                Reset();
            }
            break;


        case OPC_QNN:
        {
            CANMsg canmsg;

            canmsg.b[d0] = OPC_PNN;
            canmsg.b[d1] = (NN_temp / 256) & 0xFF;
            canmsg.b[d2] = NN_temp & 0xFF;
            canmsg.b[d3] = params[0];
            canmsg.b[d4] = params[2];
            canmsg.b[d5] = NV1;
            canmsg.b[dlc] = 6;
            canbusSend(&canmsg);
            //LED2 = 1;
            txed = 1;
            break;
        }
        case OPC_RQNPN:
            // Request to read a parameter
            if (thisNN(cmsg) == 1) {
                doRqnpn((unsigned int) cmsg->b[d3]);
            }
            break;

        case OPC_SNN:
        {
            if (Wait4NN) {
                nnH = cmsg->b[d1];
                nnL = cmsg->b[d2];
                NN_temp = nnH * 256 + nnL;
                eeWrite(EE_NN, nnH);
                eeWrite(EE_NN + 1, nnL);
                Wait4NN = 0;
                canmsg.b[d0] = OPC_NNACK;
                canmsg.b[d1] = nnH / 256;
                canmsg.b[d2] = nnL % 256;
                canmsg.b[dlc] = 3;
                canbusSend(&canmsg);
            }
            break;
        }


        case OPC_RQNP:
            if (Wait4NN) {
                CANMsg canmsg;
                canmsg.b[d0] = OPC_PARAMS;
                canmsg.b[d1] = params[0];
                canmsg.b[d2] = params[1];
                canmsg.b[d3] = params[2];
                canmsg.b[d4] = params[3];
                canmsg.b[d5] = params[4];
                canmsg.b[d6] = params[5];
                canmsg.b[d7] = params[6];
                canmsg.b[dlc] = 8;
                canbusSend(&canmsg);
                txed = 1;
            }
            break;

        case OPC_RTOF:
            if (NV1 & CFG_SAVERFID) {
                byte i;
                for (i = 0; i < 8; i++) {
                    // save rfid for SoD
                    eeWrite(EE_SCANRFID + i * 5 + 0, RFID[i].data[0]);
                    eeWrite(EE_SCANRFID + i * 5 + 1, RFID[i].data[1]);
                    eeWrite(EE_SCANRFID + i * 5 + 2, RFID[i].data[2]);
                    eeWrite(EE_SCANRFID + i * 5 + 3, RFID[i].data[3]);
                    eeWrite(EE_SCANRFID + i * 5 + 4, RFID[i].data[4]);
                }
            }
            break;

        case OPC_NVRD:
            if (thisNN(cmsg)) {
                CANMsg canmsg;
                byte nvnr = cmsg->b[d3];
                if (nvnr == 1) {
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = NN_temp & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = NV1;
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                } else if (nvnr == 2) {
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = NN_temp & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = CANID;
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                } else if (nvnr > 2 && nvnr < 28) {
                    // 5 x 8 = 40bit Allowed RFID
                    idx = (nvnr - 3) / 5;
                    var = (nvnr - 3) % 5;
                    canmsg.b[d0] = OPC_NVANS;
                    canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                    canmsg.b[d2] = NN_temp & 0xFF;
                    canmsg.b[d3] = nvnr;
                    canmsg.b[d4] = AllowedRFID[idx].data[var];
                    canmsg.b[dlc] = 5;
                    canbusSend(&canmsg);
                    txed = 1;
                }

            }
            break;

        case OPC_NVSET:
            if (thisNN(cmsg)) {
                byte nvnr = cmsg->b[d3];
                if (nvnr == 1) {
                    NV1 = cmsg->b[d4];
                    eeWrite(EE_NV, NV1);
                } else if (nvnr == 2) {
                    CANID = cmsg->b[d4];
                    eeWrite(EE_CANID, CANID);
                } else if (nvnr > 2 && nvnr < 28) {
                    // 5 x 40bit Allowed RFID
                    byte idx = (nvnr - 3) / 5;
                    byte var = (nvnr - 3) % 5;
                    AllowedRFID[idx].data[var] = cmsg->b[d4];
                    eeWrite(EE_RFID + idx * 5 + (var), cmsg->b[d4]);
                }
            }
            break;


        case OPC_NNLRN:
            if (thisNN(cmsg)) {
                isLearning = TRUE;
            }
            break;

        case OPC_NNULN:
            if (thisNN(cmsg)) {
                isLearning = FALSE;
                LED2 = PORT_OFF;
            }
            break;

        case OPC_EVLRN:
            if (isLearning) {
                nn = cmsg->b[d1] * 256 + cmsg->b[d2];
                addr = cmsg->b[d3] * 256 + cmsg->b[d4];
                idx = cmsg->b[d5];
                var = cmsg->b[d6];
                if (idx < 8) {
                    // RFID
                    RFID[idx].addr = addr;
                    eeWriteShort(EE_PORT_ADDR + 2 * idx, addr);
                } else if (idx > 7 && idx < 16) {
                    // Block
                    Sensor[idx - 8].addr = addr;
                    eeWriteShort(EE_PORT_ADDR + 2 * idx, addr);
                } else if (idx == 16) {
                    SOD = addr;
                    eeWrite(EE_SOD, addr / 256);
                    eeWrite(EE_SOD + 1, addr % 256);
                }
            }
            break;

        case OPC_NERD:
            if (thisNN(cmsg)) {
                CANMsg canmsg;
                doEV = 1;
                evIdx = 0;
                // start of day event
                canmsg.b[d0] = OPC_ENRSP;
                canmsg.b[d1] = (NN_temp / 256) & 0xFF;
                canmsg.b[d2] = NN_temp & 0xFF;
                canmsg.b[d3] = 0;
                canmsg.b[d4] = 0;
                canmsg.b[d5] = SOD / 256;
                canmsg.b[d6] = SOD % 256;
                canmsg.b[d7] = 16;
                canmsg.b[dlc] = 8;
                canbusSend(&canmsg);
                txed = 1;
            }
            break;



        default: break;
    }

    return txed;
}