Exemplo n.º 1
0
static void __sxReader( void* threadinst ) {
  iOThread th = (iOThread)threadinst;
  iOMttmFcc fcc = (iOMttmFcc)ThreadOp.getParm( th );
  iOMttmFccData data = Data(fcc);
  byte buffer[256];

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SX reader started." );
  ThreadOp.sleep( 1000 );
  
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "trying to get the FCC version..." );
  buffer[0] = 0x81;
  if( __transact(data, buffer, 1, buffer, 7 ) ) {
    TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "FCC version %d.%d", buffer[5], buffer[4] );
  }
  ThreadOp.sleep( 100 );

  while( data->run ) {
    byte cmd[2];
    Boolean ok = True;
    
    ThreadOp.sleep( 50 );
    if( ok ) {
      cmd[0] = 0x78;
      cmd[1] = 0x03;
      /*loopback test __transact( data, buffer, 224, NULL, 0);*/
      ok = __transact( data, cmd, 2, buffer, 226);
      if(ok) {
        MemOp.copy( data->sx1[0], buffer, 113 );
        MemOp.copy( data->sx1[1], buffer+113, 113 );
      }
    }
    
    ThreadOp.sleep( 50 );
    if( ok ) {
      cmd[0] = 0x78;
      cmd[1] = 0xC0;
      /*loopback test __transact( data, buffer, 190, NULL, 0);*/
      ok = __transact( data, cmd, 2, buffer, 192);
      if(ok) {
        MemOp.copy( data->sx2[0], buffer, 96 );
        MemOp.copy( data->sx2[1], buffer+96, 96 );
      }
    }

    if( ok ) {
      __evaluateFB( data );
      __updateSlots( data );
    }
    
  };

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SX reader ended." );
}
Exemplo n.º 2
0
static iONode _cmd( obj inst ,const iONode cmd ) {
  iOMttmFccData data = Data(inst);
  unsigned char out[32];
  unsigned char in [32];
  int    insize    = 0;
  iONode reply     = NULL;

  MemOp.set( in, 0x00, sizeof( in ) );

  if( cmd != NULL ) {
    if( StrOp.equals( NodeOp.getName( cmd ), wSwitchList.name() ) ) {
      int cnt = NodeOp.getChildCnt(cmd);
      int i;
      for( i = 0; i < cnt; i++ ) {
        /* build the point map */
        __getPoint(data, NodeOp.getChild(cmd, i) );
      }
      data->swInited = False;
    }
    else {
      int size = __translate( data, cmd, out, &insize );
      TraceOp.dump( NULL, TRCLEVEL_BYTE, (char*)out, size );
      if( __transact( data, out, size, in, insize ) ) {
      }
    }
  }

  /* Cleanup Node1 */
  cmd->base.del(cmd);

  return reply;
}
Exemplo n.º 3
0
static void __swTimeWatcher( void* threadinst ) {
  iOThread th = (iOThread)threadinst;
  iOP50 p50 = (iOP50)ThreadOp.getParm( th );
  iOP50Data o = Data(p50);


  ThreadOp.sleep( 100 );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Switch time watcher started." );

  do {
    ThreadOp.sleep( 10 );
    if( o->lastSwCmd != -1 && o->lastSwCmd >= o->swtime ) {
      unsigned char out[2];
      out[0] = 32;
      TraceOp.trc( name, TRCLEVEL_DEBUG, __LINE__, 9999,
                    "swTimeWatcher() END SWITCHTIME %dms", o->lastSwCmd );
      if( __transact( o, (char*)out, 1, NULL, 0 ) ) {
        o->lastSwCmd = -1;
      }
      else
        TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "swTimeWatcher() Could not send reset byte!" );
    }
    if( o->lastSwCmd != -1 ) {
      o->lastSwCmd += 10;
    }
  } while( o->run );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Switch time watcher ended." );
}
Exemplo n.º 4
0
static void __feedbackReader( void* threadinst ) {
  iOThread th = (iOThread)threadinst;
  iOP50 p50 = (iOP50)ThreadOp.getParm( th );
  iOP50Data o = Data(p50);
  unsigned char* fb = allocMem(256);

  ThreadOp.sleep( 100 );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Feedback reader started." );
  do {
    unsigned char out[256];
    unsigned char in [512];

    ThreadOp.sleep( o->psleep );
    if( o->fbmod == 0 )
      continue;

    out[0] = (unsigned char)(128 + o->fbmod);
    if( __transact( o, (char*)out, 1, (char*)in, o->fbmod * 2 ) ) {
      if( memcmp( fb, in, o->fbmod * 2 ) != 0 ) {
        /* inform listener */
        __evaluateState( o, fb, in, o->fbmod * 2);
        memcpy( fb, in, o->fbmod * 2 );
      }
    }
  } while( o->run );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Feedback reader ended." );
}
Exemplo n.º 5
0
static iONode _cmd( obj inst, const iONode nodeA ) {
  iOP50Data o = Data(inst);
  unsigned char out[256];
  unsigned char in [512];
  int insize = 0;
  iONode nodeB = NULL;

  if( nodeA != NULL ) {
    int size = __translate( o, nodeA, out, &insize );
    if( __transact( o, (char*)out, size, (char*)in, insize ) ) {
      /* Inform timer. */
      if( StrOp.equals( NodeOp.getName( nodeA ), wSwitch.name() ) ) {
        o->lastSwCmd = 0;
        ThreadOp.sleep( 100 );
      }
      /* inform listener */
      if( insize > 0 ) {
        char* s = StrOp.byteToStr( in, insize );
        nodeB = NodeOp.inst( NodeOp.getName( nodeA ), NULL, ELEMENT_NODE );
        wResponse.setdata( nodeB, s );
        StrOp.free(s);
      }
    }
    /* Cleanup Node1 */
    nodeA->base.del(nodeA);
  }
  /* return Node2 */
  return nodeB;
}
Exemplo n.º 6
0
static void _halt( obj inst, Boolean poweroff ) {
  iOP50Data data = Data(inst);
  unsigned char p50[2];

  data->run = False;
  if( poweroff ) {
    p50[0] = (unsigned char)97;
    __transact( data, (char*)p50, 1, NULL, 0 );
  }
  SerialOp.close( data->serial );

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Shutting down <%s>...", data->iid );
}
Exemplo n.º 7
0
static void _halt( obj inst, Boolean poweroff ) {
  iOSprogData data = Data(inst);
  data->run = False;
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Shutting down [%s]...", data->iid );
  if( poweroff ) {
    char outa[32];
    StrOp.fmtb( outa, "-\r" );
    data->power = False;
    __transact( (iOSprog)inst, outa, StrOp.len(outa), NULL, 0, 1 );
  }
  ThreadOp.sleep(1000);
  data->commOK = False;
  SerialOp.close( data->serial );
  return;
}
Exemplo n.º 8
0
static iONode _cmd( obj inst ,const iONode nodeA ) {
  iOSprogData data = Data(inst);
  iONode nodeB = NULL;
  char outa[100] = {'\0'};
  char ina[100]  = {'\0'};
  int insize = 0;

  if( nodeA != NULL ) {
    int repeat = __translate( (iOSprog)inst, nodeA, outa, &insize );
    if( StrOp.len(outa) > 0 ) {
      __transact( (iOSprog)inst, outa, StrOp.len(outa), ina, insize, repeat );
    }
    /* Cleanup Node1 */
    nodeA->base.del(nodeA);
  }

  /* return Node2 */
  return nodeB;
}
Exemplo n.º 9
0
static int __translate( iOMttmFccData data, iONode node, byte* out, int *insize ) {
  *insize = 0;

  if( StrOp.equals( NodeOp.getName( node ), wFbInfo.name() ) ) {
    __updateFB( data, node );
    data->fbInited = False;
  }
  /* Switch command. */
  else if( StrOp.equals( NodeOp.getName( node ), wSwitch.name() ) ) {
    int bus   = wSwitch.getbus( node ) & 0x01;
    int addr  = wSwitch.getaddr1( node ) & 0x7F;
    byte pin  = 0x01 << ( wSwitch.getport1( node ) - 1 );
    byte mask = ~pin;

    iOPoint point = __getPoint(data, node);
    if( point != NULL ) {
      point->lastcmd = SystemOp.getTick();
    }

    out[0] = bus;
    out[1] = addr | 0x80;
    out[2] = 0x01 << ( wSwitch.getport1( node ) - 1 );

    /* reset pin to 0: */
    out[2] = data->swstate[bus][addr] & mask;

    if( StrOp.equals( wSwitch.getcmd( node ), wSwitch.turnout ) )
      out[2] |= pin;
    /* save new state: */
    data->swstate[bus][addr] = out[2];
    *insize = 1;
    return 3;
  }

  /* Output command */
  else if( StrOp.equals( NodeOp.getName( node ), wOutput.name() ) ) {
    int bus  = wOutput.getbus( node ) & 0x01;
    int addr = wOutput.getaddr( node );
    int port = wOutput.getport( node );
    int gate = wOutput.getgate( node );
    int action = StrOp.equals( wOutput.getcmd( node ), wOutput.on ) ? 0x01:0x00;
    byte pin = 0x01 << ( port - 1 );
    byte mask = ~pin;

    out[0] = bus;
    out[1] = addr | 0x80;

    /* reset pin to 0: */
    out[2] = data->swstate[bus][addr] & mask;

    if( action )
      out[2] |= pin;
    /* save new state: */
    data->swstate[bus][addr] = out[2];
    *insize = 1;
    return 3;
  }


  /* System command. */
  /*
    Gleisspannung ein (SX1/2-Bus 0): Vom PC:  0x00  0xFF  0x01
    Gleisspannung aus (SX1/2-Bus 0): Vom PC:  0x00  0xFF  0x00
    Gleisspannung ein (SX1/2-Bus 1): Vom PC:  0x01  0xFF  0x01
    Gleisspannung aus (SX1/2-Bus 1): Vom PC:  0x01  0xFF  0x00
    Zum PC: 0x00 Zum PC:  0x00 Zum PC:  0x00 Zum PC:  0x00
  */
  else if( StrOp.equals( NodeOp.getName( node ), wSysCmd.name() ) ) {
    const char* cmd = wSysCmd.getcmd( node );
    if( StrOp.equals( cmd, wSysCmd.stop ) || StrOp.equals( cmd, wSysCmd.ebreak ) ) {
      out[0] = 0x00;
      out[1] = 0xFF;
      out[2] = 0x00;
      *insize = 1; /* Return code from FCC. */
      TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "Power OFF" );
      return 3;
    }
    else if( StrOp.equals( cmd, wSysCmd.go ) ) {
      out[0] = 0x00;
      out[1] = 0xFF;
      out[2] = 0x01;
      *insize = 1; /* Return code from FCC. */
      TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "Power ON" );
      return 3;
    }
  }

  /* Loc command.*/
  else if( StrOp.equals( NodeOp.getName( node ), wLoc.name() ) ) {
    int  speed = 0;
    byte in = 0;
    Boolean fn = wLoc.isfn( node );
    int    dir = wLoc.isdir( node );
    int  spcnt = wLoc.getspcnt( node );
    byte horn;

    int index = 0;

    iOSlot slot = __getSlot(data, node );

    if( slot == NULL ) {
      TraceOp.trc( name, TRCLEVEL_WARNING, __LINE__, 9999, "could not get slot for loco %s", wLoc.getid(node) );
      return 0;
    }

    if( data->dummyio ) {
      __updateSlots(data);
    }


    spcnt = slot->steps;

    if( wLoc.getV( node ) != -1 ) {
      if( StrOp.equals( wLoc.getV_mode( node ), wLoc.V_mode_percent ) )
        speed = (wLoc.getV( node ) * spcnt) / 100;
      else if( wLoc.getV_max( node ) > 0 )
        speed = (wLoc.getV( node ) * spcnt) / wLoc.getV_max( node );
    }

    if( slot->ebreak && speed > 0 ) {
      speed++;
    }

    TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "loc=%s addr=%d speed=%d steps=%d lights=%s dir=%s",
        wLoc.getid(node), wLoc.getaddr(node), speed, spcnt, fn?"on":"off", dir?"forwards":"reverse" );

    if( slot->sx1 ) {
      /* native selectrix SX1 */
      TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "SX1 loco command for %s", wLoc.getid(node) );
      out[0] = wLoc.getbus(node)&0x01;
      out[1] = wLoc.getaddr(node);
      out[1] |= 0x80;
      /*
      SX1-Loks werden wie bisher direkt über die entsprechenden SX1-Kanäle des SX1/2-Bus- Systems 0 gesteuert.
      Die Kanalbelegung ist:
      Bits 0 bis 4: Fahrstufen von 0 bis 31 
      Bit 5:        Fahrtrichtung (0 entspricht vorwaerts, 1 entspricht rueckwaerts) 
      Bit 6:        Licht (0 bedeutet Licht aus, 1 bedeutet Licht ein) 
      Bit 7:        Horn (0 bedeutet Horn aus, 1 bedeutet Horn ein) 
      */
      out[2] = speed & 0x1F;
      out[2] |= (wLoc.isdir(node) ? 0x00:0x20);
      out[2] |= (wLoc.isfn(node)  ? 0x40:0x00);
      if (!slot->sx1aux1 && !slot->sx1aux2)
        horn = slot->f1_8 & 0x01;    /* Horn at F1 */
      else if (slot->sx1aux1 && !slot->sx1aux2)
        horn = slot->f9_16 & 0x01;   /* Horn at F9 */
      else
        horn = 0x00;
      out[2] |= ((horn & 0x01) ? 0x80:0x00);

      slot->speed = speed;
      slot->dir = wLoc.isdir(node);
      slot->lights = wLoc.isfn(node);
      slot->lastcmd = SystemOp.getTick();

      *insize = 1;
      return 3;
    }


    index = slot->index;
    /* Lights 
      ON : 0x79 0x05 Index 0x02 0x00
      OFF: 0x79 0x05 Index 0x00 0x00
    */
    out[0] = 0x79;
    out[1] = 0x05;
    out[2] = index;
    out[3] = fn?0x02:0x00;
    out[4] = 0x00;
    __transact( data, out, 5, &in, 1 );

    /*
      Verändern der Fahrstufe einer SX2-, DCC- oder MM-Lok:
      Vom PC: 0x79  0x03  Index FS  0x00
      Zum PC: gleich 0x00 (im Erfolgsfalle)
      ungleich 0x00 (im Fehlerfalle)

      Verändern der Fahrstufe und der Fahrtrichtung einer SX2-, DCC- oder MM-Lok:
      Vom PC: 0x79  0x13  Index FSFR  0x00
      Zum PC:
      gleich 0x00
      ungleich 0x00
      Index ist der bei der Anmeldung der betreffenden Lok an die FCC-Digitalzentrale zurückgegebene Wert.
      FSFR ist der, gemäß der oben stehenden Tabelle, umgerechnete Wert der neuen Fahrstufe, wobei das höchstwertige
      Bit die neue Fahrtrichtung bestimmt!
     */
    out[0] = 0x79;
    out[1] = 0x13;
    out[2] = index;
    out[3] = speed + (dir?0x00:0x80);
    out[4] = 0x00;
    *insize = 1; /* Return code from FCC. */
    return 5;

  }

  /* Function command. */
  else if( StrOp.equals( NodeOp.getName( node ), wFunCmd.name() ) ) {
    Boolean f1  = wFunCmd.isf1 ( node );
    Boolean f2  = wFunCmd.isf2 ( node );
    Boolean f3  = wFunCmd.isf3 ( node );
    Boolean f4  = wFunCmd.isf4 ( node );
    Boolean f5  = wFunCmd.isf5 ( node );
    Boolean f6  = wFunCmd.isf6 ( node );
    Boolean f7  = wFunCmd.isf7 ( node );
    Boolean f8  = wFunCmd.isf8 ( node );
    Boolean f9  = wFunCmd.isf9 ( node );
    Boolean f10 = wFunCmd.isf10( node );
    Boolean f11 = wFunCmd.isf11( node );
    Boolean f12 = wFunCmd.isf12( node );
    Boolean f13 = wFunCmd.isf13( node );
    Boolean f14 = wFunCmd.isf14( node );
    Boolean f15 = wFunCmd.isf15( node );
    Boolean f16 = wFunCmd.isf16( node );
    byte in = 0;
    iOSlot slot = __getSlot(data, node );

    if( slot == NULL ) {
      TraceOp.trc( name, TRCLEVEL_WARNING, __LINE__, 9999, "could not get slot for loco %s", wLoc.getid(node) );
      return 0;
    }


    if( slot->sx1 ) {
      /* native selectrix SX1 */
      int   addr = wFunCmd.getaddr( node );

      if (slot->sx1aux2) {
        out[0] = wLoc.getbus(node)&0x01;
        out[1] = slot->sx1aux2;
        out[1] |= 0x80;
        out[2] = (f9 << 0 | f10 << 1 | f11 << 2 | f12 << 3 | f13 << 4 | f14 << 5 | f15 << 6 | f16 << 7);
        TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "SX1 Auxchannel 2 command for loco [%s]", wLoc.getid(node) );
        slot->f9_16 = out[2];
        slot->lastcmd = SystemOp.getTick();
        __transact( data, out, 3, &in, 1 );
      }

      if (slot->sx1aux1) {
        out[0] = wLoc.getbus(node)&0x01;
        out[1] = slot->sx1aux1;
        out[1] |= 0x80;
        out[2] = (f1 << 0 | f2 << 1 | f3 << 2 | f4 << 3 | f5 << 4 | f6 << 5 | f7 << 6 | f8 << 7);
        TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "SX1 Auxchannel 1 command for loco [%s]", wLoc.getid(node) );
        slot->f1_8 = out[2];
        slot->lastcmd = SystemOp.getTick();
        __transact( data, out, 3, &in, 1 );
      }

      TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "SX1 function command for %s", wLoc.getid(node) );
      out[0] = wLoc.getbus(node)&0x01;
      out[1] = wLoc.getaddr(node);
      out[1] |= 0x80;
      out[2] = slot->speed & 0x1F;
      out[2] |= (slot->dir ? 0x00:0x20);
      slot->lights = wLoc.isfn(node);    /* save light function */ 
      out[2] |= (slot->lights ? 0x40:0x00);
      if (!slot->sx1aux1 && !slot->sx1aux2) {
        out[2] |= (f1 ? 0x80:0x00);      /* Horn at F1 */
      slot->f1_8 = f1 ? 0x01:0x00;
      } 
      else if (slot->sx1aux1 && !slot->sx1aux2) {
        out[2] |= (f9 ? 0x80:0x00);      /* Horn at F9 */
        slot->f9_16 = f9 ? 0x01 : 0x00;
      } /* No else */

      slot->lastcmd = SystemOp.getTick();

      *insize = 1;
      return 3;
    }
    else {
      TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "function command for %s", wLoc.getid(node) );
      out[0] = 0x79;
      out[1] = 0x16;
      out[2] = slot->index;
      out[3] = (f1 << 0 | f2 << 1 | f3 << 2 | f4 << 3 | f5 << 4 | f6 << 5 | f7 << 6 | f8 << 7);
      out[4] = (f9 << 0 | f10 << 1 | f11 << 2 | f12 << 3 | f13 << 4 | f14 << 5 | f15 << 6 | f16 << 7);
      out[5] = 0x00;
      slot->f1_8  = out[3];
      slot->f9_16 = out[4];
      *insize = 1;
      return 6;
    }
    
  }


  /* Program command. */
  else if( StrOp.equals( NodeOp.getName( node ), wProgram.name() ) ) {
    if( wProgram.getcmd( node ) == wProgram.set ) {
      int cv    = wProgram.getcv( node );
      int value = wProgram.getvalue( node );
      int addr  = wProgram.getaddr( node );

      if( wProgram.ispom(node) ) {
        TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "POM: set CV%d of SX2 loc %d to %d...", cv, addr, value );
        /* SX2: 0x7A Adresse (High) Adresse (Low) PA (High) PA (Low) Wert */
        out[0] = 0x7A;
        out[1] = addr/256;
        out[2] = addr%256;
        out[3] = cv/256;
        out[4] = cv%256;
        out[5] = value;
        *insize = 1;
        return 6;
      }
      else {
        TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "set CV%d of SX2 loc %d to %d...", cv, addr, value );
        /* SX2: 0x83 0xCA High Low Wert */
        out[0] = 0x83;
        out[1] = 0xCA;
        out[2] = cv/256;
        out[3] = cv%256;
        out[4] = value;
        *insize = 3;
        return 5;
      }
    }
    else if( wProgram.getcmd( node ) == wProgram.get ) {
      int cv    = wProgram.getcv( node );
      int addr  = wProgram.getaddr( node );
      if( wProgram.ispom(node) ) {
        TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "*** not supported *** POM: read CV%d of loc %d...", cv, addr );
      }
      else {
        TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "read CV%d of SX2 loc %d...", cv, addr );
        /* SX2: 0x83 0xC2 High Low 0x00 */
        out[0] = 0x83;
        out[1] = 0xC2;
        out[2] = cv/256;
        out[3] = cv%256;
        out[4] = 0;
        *insize = 3;
        return 5;
      }
    }

  }

  return 0;
}
Exemplo n.º 10
0
static iOSlot __getSlot(iOMttmFccData data, iONode node) {
  int steps = wLoc.getspcnt(node);
  int addr  = wLoc.getaddr(node);
  int fncnt = wLoc.getfncnt(node);
  Boolean ebreak = True;
  Boolean sx1 = False;
  byte index = 0xFF;
  iOSlot slot = NULL;
  byte cmd[32] = {0x79, 0x01};

  slot = (iOSlot)MapOp.get( data->lcmap, wLoc.getid(node) );
  if( slot != NULL ) {
    TraceOp.trc( name, TRCLEVEL_DEBUG, __LINE__, 9999, "slot exist for %s", wLoc.getid(node) );
    return slot;
  }

  if( StrOp.equals( wLoc.prot_S, wLoc.getprot(node) ) ) {
    steps = 31;
    sx1 = True;
    ebreak = False;

    TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "sx1, steps=%d, fncnt=%d", steps, fncnt );
  }
  /*
    Die DCC-Lok mit der langen Adresse 1234 und 126 Fahrstufen soll an die FCC- Digitalzentrale angemeldet werden:
    Bestimmung: 1234 (binär: 00010011010010) DCC-Lokadresse: 00010011010010 00 entspricht 0x1348
    Es ist daher Folgendes an die FCC-Digitalzentrale zu senden: Vom PC:  0x79  0x01  0x13  0x48  0x07
   */
  else if( StrOp.equals( wLoc.prot_N, wLoc.getprot(node) ) ) {
    /* short DCC */
    addr = addr << 2;
    cmd[4] = steps > 100 ? 0x05:(steps > 14 ? 0x81:0x91);
    steps =  steps > 100 ? 126:(steps > 14 ? 28:14);
    TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "short DCC, steps=%d, fncnt=%d", steps, fncnt );
  }
  else if( StrOp.equals( wLoc.prot_L, wLoc.getprot(node) ) ) {
    /* long DCC */
    addr = addr << 2;
    cmd[4] = steps > 100 ? 0x07:(steps > 14 ? 0x83:0x93);
    steps =  steps > 100 ? 126:(steps > 14 ? 28:14);
    TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "long DCC, steps=%d, fncnt=%d", steps, fncnt );
  }
  else if( StrOp.equals( wLoc.prot_M, wLoc.getprot(node) ) ) {
    /* MM */
    /*
    Die MM-Lok mit der Adresse 218 soll an die FCC-Digitalzentrale angemeldet werden:
    Bestimmung: 218 (binär: 00000011011010) MM-Lokadresse: 00000011011010 00 entspricht 0x0368
    Es ist daher Folgendes an die FCC-Digitalzentrale zu senden: Vom PC:  0x79  0x01  0x03  0x68  0x02
     */
    addr = addr << 2;
    cmd[4] = fncnt == 4 ? 0x82:0x92;
    steps = 14;
    TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "MM, steps=%d, fncnt=%d", steps, fncnt );
  }
  else {
    /*
    Die SX2-Lok mit der Adresse 5678 soll an die FCC-Digitalzentrale angemeldet werden:
    Rechnung: 5678 / 100 = 56 (binär: 0111000) Rest 78 (binär: 1001110)
    SX2-Lokadresse: 0111000 1001110 00 entspricht 0x7138
    Es ist daher Folgendes an die FCC-Digitalzentrale zu senden: Vom PC:  0x79  0x01  0x71  0x38  0x04
    */
    addr = (wLoc.getaddr(node) / 100) << 9;
    addr = addr + ((wLoc.getaddr(node) % 100) << 2);

    /* default SX2 */
    cmd[4] = 0x04;
    steps = 127;
    ebreak = False;
    TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "default SX2, steps=%d, fncnt=%d", steps, fncnt );
  }

  cmd[2] = addr / 256;
  cmd[3] = addr % 256;


  if( sx1 || __transact( data, cmd, 5, &index, 1 ) ) {
    TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "got index %d for %s", index, wLoc.getid(node) );
    slot = allocMem( sizeof( struct slot) );
    slot->addr = addr;
    slot->index = index;
    slot->protocol = cmd[4];
    slot->steps = steps;
    slot->ebreak = ebreak;
    slot->sx1 = sx1;
    if (sx1) {
      slot->sx1aux1 = slot->sx1aux2 = 0;
      if (fncnt > 0) {
        slot->sx1aux1 = addr+1;	/* First SX1 auxchannel at loco address + 1 */
        TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "SX1 Auxchannel 1 Addr=%d", slot->sx1aux1 );
      }
      if (fncnt > 8) {
        slot->sx1aux2 = addr+2;	/* Second SX1 auxchannel at loco address + 2 */
        TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "SX1 Auxchannel 2 Addr=%d", slot->sx1aux2 );
      }
    }
    slot->bus = wLoc.getbus(node);
    slot->id = StrOp.dup(wLoc.getid(node));
    if( MutexOp.wait( data->lcmux ) ) {
      MapOp.put( data->lcmap, wLoc.getid(node), (obj)slot);
      MutexOp.post(data->lcmux);
    }
    TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "slot created for %s", wLoc.getid(node) );
  }

  return slot;
}
Exemplo n.º 11
0
static void __sprogReader( void* threadinst ) {
  iOThread th = (iOThread)threadinst;
  iOSprog sprog = (iOSprog)ThreadOp.getParm( th );
  iOSprogData data = Data(sprog);

  char in[256] = {0};
  int idx = 0;
  int retry = 0;

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SPROG reader started." );
  ThreadOp.sleep( 1000 );

  StrOp.fmtb( in, "?\r" );
  __transact( sprog, in, StrOp.len(in), NULL, 0, 1 );

  do {

    ThreadOp.sleep( 10 );

    if( data->run && data->commOK && MutexOp.wait( data->mux ) ) {
      int available = SerialOp.available(data->serial);
      if( available > 0 ) {
        if( SerialOp.read(data->serial, &in[idx], 1) ) {
          TraceOp.dump( NULL, TRCLEVEL_DEBUG, (char*)in, StrOp.len(in) );
          if( idx > 254 ) {
            in[idx] = 0;
            TraceOp.trc( name, TRCLEVEL_WARNING, __LINE__, 9999, "reader overflow [%d]\n%s", idx, in );
            idx = 0;
          }
          else if( in[idx] == '\r' || in[idx] == '\n' ) {
            in[idx+1] = '\0';
            StrOp.replaceAll( in, '\n', '\0' );
            StrOp.replaceAll( in, '\r', '\0' );
            if( StrOp.len(in) > 0 ) {
              TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999, "SPROG read: [%s]", in );
              __handleResponse(sprog, in);
            }
            idx = 0;
            in[idx] = '\0';
          }
          else if( StrOp.equals( in, "P> ") || StrOp.equals( in, " P>") || StrOp.equals( in, " P> ") ) {
            idx = 0;
            in[idx] = '\0'; /* ignore prompt */
          }
          else {
            idx++;
          }
        }
      }
      else if( available == -1 || SerialOp.getRc(data->serial) > 0 ) {
        /* device error */
        data->commOK = False;
        SerialOp.close(data->serial);
        TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "device error" );
      }

      /* Release the mutex. */
      MutexOp.post( data->mux );
    }
    else if(!data->commOK) {
      retry++;
      if( retry >= 500 ) {
        retry = 0;
        data->commOK = SerialOp.open( data->serial );
        if(data->commOK) {
          SerialOp.setDTR(data->serial, True);
          SerialOp.setRTS(data->serial, True);
        }
      }
    }

  } while(data->run);

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SPROG reader ended." );
  ThreadOp.base.del(th);
}
Exemplo n.º 12
0
static void __sprogWriter( void* threadinst ) {
  iOThread th = (iOThread)threadinst;
  iOSprog sprog = (iOSprog)ThreadOp.getParm( th );
  iOSprogData data = Data(sprog);
  int slotidx = 0;

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SPROG writer started." );

  while(data->run) {

    ThreadOp.sleep(25);

    if( data->power ) {
      if( data->slots[slotidx].addr > 0 ) {
        byte dcc[12];
        char cmd[32] = {0};
        char out[64] = {0};
        char in [64] = {0};
        TraceOp.trc( name, TRCLEVEL_DEBUG, __LINE__, 9999, "slot refresh for %d", data->slots[slotidx].addr );

        if( data->slots[slotidx].V == data->slots[slotidx].V_prev && data->slots[slotidx].changedfgrp == 0 ) {
          if( data->slots[slotidx].idle + 8000 < SystemOp.getTick() ) {
            TraceOp.trc( name, TRCLEVEL_MONITOR, __LINE__, 9999,
                "slot %d purged for loco address %d", slotidx, data->slots[slotidx].addr );
            data->slots[slotidx].addr = 0;
            data->slots[slotidx].idle = 0;
            data->slots[slotidx].fgrp = 0;
            data->slots[slotidx].changedfgrp = 0;
            data->slots[slotidx].V_prev = 0;
            data->slots[slotidx].V = 0;
            slotidx++;
            continue;
          }
        }
        else {
          data->slots[slotidx].V_prev = data->slots[slotidx].V;
          data->slots[slotidx].fgrp = data->slots[slotidx].changedfgrp;
          data->slots[slotidx].changedfgrp = 0;
          data->slots[slotidx].idle = SystemOp.getTick();
        }


        if( data->slots[slotidx].steps > 28 )  {
          int size = speedStep128Packet(dcc, data->slots[slotidx].addr,
              data->slots[slotidx].longaddr, data->slots[slotidx].V, data->slots[slotidx].dir );
          __byteToStr( cmd, dcc, size );
          StrOp.fmtb( out, "O %s\r", cmd );
          TraceOp.trc( name, TRCLEVEL_BYTE, __LINE__, 9999, "128 DCC out: %s", out );
          __transact( sprog, out, StrOp.len(out), in, 3, 1 );
        }
        else if( data->slots[slotidx].steps == 28 )  {
          int size = speedStep28Packet(dcc, data->slots[slotidx].addr,
              data->slots[slotidx].longaddr, data->slots[slotidx].V, data->slots[slotidx].dir );
          __byteToStr( cmd, dcc, size );
          StrOp.fmtb( out, "O %s\r", cmd );
          TraceOp.trc( name, TRCLEVEL_BYTE, __LINE__, 9999, "28 DCC out: %s", out );
          __transact( sprog, out, StrOp.len(out), in, 3, 1 );
        }
        else {
          int size = speedStep14Packet(dcc, data->slots[slotidx].addr,
              data->slots[slotidx].longaddr, data->slots[slotidx].V,
              data->slots[slotidx].dir, data->slots[slotidx].lights );
          __byteToStr( cmd, dcc, size );
          StrOp.fmtb( out, "O %s\r", cmd );
          TraceOp.trc( name, TRCLEVEL_BYTE, __LINE__, 9999, "14 DCC out: %s", out );
          __transact( sprog, out, StrOp.len(out), in, 3, 1 );
        }

        if( data->slots[slotidx].fgrp > 0 ) {
          int size = 0;

          ThreadOp.sleep(25);
          if( data->slots[slotidx].fgrp == 1 ) {
            size = function0Through4Packet(dcc, data->slots[slotidx].addr,
                data->slots[slotidx].longaddr,
                data->slots[slotidx].fn[0],
                data->slots[slotidx].fn[1],
                data->slots[slotidx].fn[2],
                data->slots[slotidx].fn[3],
                data->slots[slotidx].fn[4] );
          }
          else if( data->slots[slotidx].fgrp == 2 ) {
            size = function5Through8Packet(dcc, data->slots[slotidx].addr,
                data->slots[slotidx].longaddr,
                data->slots[slotidx].fn[5],
                data->slots[slotidx].fn[6],
                data->slots[slotidx].fn[7],
                data->slots[slotidx].fn[8] );
          }
          else if( data->slots[slotidx].fgrp == 3 ) {
            size = function9Through12Packet(dcc, data->slots[slotidx].addr,
                data->slots[slotidx].longaddr,
                data->slots[slotidx].fn[9],
                data->slots[slotidx].fn[10],
                data->slots[slotidx].fn[11],
                data->slots[slotidx].fn[12] );
          }
          else if( data->slots[slotidx].fgrp == 4 || data->slots[slotidx].fgrp == 5 ) {
            size = function13Through20Packet(dcc, data->slots[slotidx].addr,
                data->slots[slotidx].longaddr,
                data->slots[slotidx].fn[13],
                data->slots[slotidx].fn[14],
                data->slots[slotidx].fn[15],
                data->slots[slotidx].fn[16],
                data->slots[slotidx].fn[17],
                data->slots[slotidx].fn[18],
                data->slots[slotidx].fn[19],
                data->slots[slotidx].fn[20] );
          }
          else if( data->slots[slotidx].fgrp == 6 || data->slots[slotidx].fgrp == 7 ) {
            size = function21Through28Packet(dcc, data->slots[slotidx].addr,
                data->slots[slotidx].longaddr,
                data->slots[slotidx].fn[21],
                data->slots[slotidx].fn[22],
                data->slots[slotidx].fn[23],
                data->slots[slotidx].fn[24],
                data->slots[slotidx].fn[25],
                data->slots[slotidx].fn[26],
                data->slots[slotidx].fn[27],
                data->slots[slotidx].fn[28] );
          }

          __byteToStr( cmd, dcc, size );
          StrOp.fmtb( out, "O %s\r", cmd );
          TraceOp.trc( name, TRCLEVEL_BYTE, __LINE__, 9999, "function group %d DCC out: %s", data->slots[slotidx].changedfgrp, out );
          __transact( sprog, out, StrOp.len(out), in, 3, 1 );
        }

        slotidx++;
      }
      else {
        slotidx = 0;
      }
    }


  };

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SPROG writer ended." );
  ThreadOp.base.del(th);
}