To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.robotics.nxt.nxthackingOpen lugnet.robotics.nxt.nxthacking in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / NXT / NXT Firmware Hacking / 30
29  |  31
Subject: 
More firmware enhancements
Newsgroups: 
lugnet.robotics.nxt.nxthacking
Date: 
Thu, 22 Mar 2007 21:23:56 GMT
Viewed: 
16838 times
  
I have implemented OP_WAIT and a variant of OP_WAIT which takes a variable
rather than an immediate numeric value (which in nbc is called "waitv").  I also
modified NBC to accept a command line switch that tells it whether the firmware
supports waits or not.

Here's the code:

// in cCmdInterpUnop1 (c_cmd.c)
    case OP_WAIT:
    case OP_WAITV:
    {
      ULONG WaitMS;
      CLUMP_REC* pClumpRec = &(VarsCmd.pAllClumps[VarsCmd.CallerClump]);
      pClumpRec->Sleeping = TRUE;
      if (opCode == OP_WAITV) {
        pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
        WaitMS = cCmdGetVal(pArg1, TypeCode1);
      }
      else
        WaitMS = Arg1;
      pClumpRec->WakeTick = IOMapCmd.Tick + WaitMS;
    }
    break;

// in cCmdActivateProgram (c_cmd.c)

    VarsCmd.pAllClumps[i].Sleeping = FALSE;
    VarsCmd.pAllClumps[i].WakeTick = 0;

// in cCmdInterpFromClump (c_cmd.c)

  //Resolve clump record structure and current instruction pointer
  pClumpRec = &(VarsCmd.pAllClumps[Clump]);

  // is this clump waiting?
  if (pClumpRec->Sleeping)
  {
    // should it wake up?
    if (pClumpRec->WakeTick <= dTimerRead())
    {
      // wake up clump
      pClumpRec->Sleeping = FALSE;
      // go on executing code as before
    }
    else {
      // if it should not wake up then return from this routine now
      return NO_ERR;
    }
  }

  pInstr = (VarsCmd.pCodespace + pClumpRec->CodeStart + pClumpRec->PC);

// in c_cmd.h

typedef struct
{
  CODE_INDEX  CodeStart;
  CODE_INDEX  CodeEnd;
  CODE_INDEX PC;
  UBYTE     InitFireCount;
  UBYTE     CurrFireCount; //AKA ShortCount
  CLUMP_ID  Link;

  UBYTE     Priority;

  CLUMP_ID* pDependents;
  UBYTE     DependentCount;
  ULONG     WakeTick; // JCH
  UBYTE     Sleeping; // JCH
} CLUMP_REC;

// in c_cmd_bytecodes.h
#define OPCODE_COUNT  0x37

#define OP_WAITV    0x36  // var

I also fixed a major bug in OP_REPLACE.  Here's the code:

// in c_cmd.c

UWORD cCmdArrayDimensions(DS_ELEMENT_ID DSElementID)
{
  NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
  UWORD result = 0;
  while (cCmdDSType(DSElementID) == TC_ARRAY)
  {
    result++;
    DSElementID = INC_ID(DSElementID);
  }
  return result;
}

// in cCmdInterpOther (c_cmd.c)

    case OP_REPLACE:
    {
      //Arg1 - Dst
      //Arg2 - Src
      //Arg3 - Index
      //Arg4 - New val / array of vals
      UWORD SrcDims, NewValDims;

      Arg1 = pCode[1];
      Arg2 = pCode[2];
      Arg3 = pCode[3];
      Arg4 = pCode[4];

      NXT_ASSERT(cCmdDSType(Arg1) == TC_ARRAY);
      NXT_ASSERT(cCmdDSType(Arg2) == TC_ARRAY);

      //Copy Src to Dst
      //!!! Could avoid full data copy if we knew which portion to overwrite
      if (Arg1 != Arg2)
      {
        Status = cCmdInterpPolyUnop2(OP_MOV, Arg1, 0, Arg2, 0);
        if (IS_ERR(Status))
          return Status;
      }

      DVIndex1 = cCmdGetDVIndex(Arg1, 0);
      //Copy new val to Dst
      if (Arg3 != NOT_A_DS_ID)
      {
        pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
        ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
      }
      else
      {
        //Index input unwired
        ArgVal3 = 0;
      }

      ArrayCount1 = cCmdArrayCount(Arg1, 0);
      //Bounds check
      //If array index (ArgVal3) is out of range, just pass out the copy of Src
(effectively no-op)
      if (ArgVal3 >= ArrayCount1)
        return (NO_ERR);

      SrcDims    = cCmdArrayDimensions(Arg2);
      NewValDims = cCmdArrayDimensions(Arg4);
      // if the new value argument has an array dimension that is 1 less than
      // the array dimension of the source array then use MOV to copy data
//      if (cCmdDSType(Arg4) != TC_ARRAY)
      if (NewValDims == (SrcDims-1))
      {
        Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg1),
ARRAY_ELEM_OFFSET(DVIndex1, ArgVal3), Arg4, 0);
        if (IS_ERR(Status))
          return Status;
      }
      else if (NewValDims == SrcDims)
      {
        DVIndex4 = cCmdGetDVIndex(Arg4, 0);

        ArrayCount4 = cCmdArrayCount(Arg4, 0);
        if (ArrayCount1 - ArgVal3 < ArrayCount4)
          MinCount = (UWORD)(ArrayCount1 - ArgVal3);
        else
          MinCount = ArrayCount4;

        for (i = 0; i < MinCount; i++)
        {
          Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg1),
ARRAY_ELEM_OFFSET(DVIndex1, ArgVal3 + i), INC_ID(Arg4),
ARRAY_ELEM_OFFSET(DVIndex4, i));
          if (IS_ERR(Status))
            return Status;
        }
      }
      else
      {
        // any other situation is unsupported
        NXT_BREAK;
        return 0;
      }
    }
    break;

I will be uploading a copy of the firmware with these enhancements later today.

John Hansen



1 Message in This Thread:

Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR