Giter Club home page Giter Club logo

Comments (2)

tino avatar tino commented on July 20, 2024

There are actually two types of handlers, which is what causes the confusion I think. There are handlers for 'normal' commands, like "report analog pin", "report digital port" and "report version". And there are also handlers for sysex-commands, like "report firmware". The difference is that the former take a specified number of arguments (usually two, a least and most significant byte, to be able to define numbers higher than 256) and the latter take any number of arguments, as everything is read until the END_SYSEX bytes comes along. See the iterate method for how this works.

So if you want to define a non-sysex handler, use the args you need. If you define a handler for a sysex command (which you probably want to do for custom commands), you can do the same if the number of arguments is fixed, or use *data as in the _handle_report_firmware handler.

Looking at it now, I might split the handler in two types later (sysex/non-sysex) as that looks a little clearer.

About moving towards 2.2/2.3, I think the only thing really needed is implementing the remaining sysex commands for capabilities querying and the like. But it might include some refactoring to make this easier. I will probably look at this next week.

from pyfirmata.

cefn avatar cefn commented on July 20, 2024

Thanks for taking the time for such a detailed reply. This information should be more than enough for me to put together my code examples.

In particular I'm aiming to write logic on both sides of the connection which permits the marshalling and unmarshalling of canonical Arduino data types (based on 8-bit), into a 7-bit transport, as per the code below in Arduino, and the equivalent code in python below that. Please note these code blocks have not been tested, but in some ways code is its own best description.

/** Symmetric with decodefrom7 - encodes bytes to 7-bit values, with an overflow byte 
* to store extra bits. Returns the number of total bytes written to the destination byte array*/
int encodeTo7(byte* srcBytes, byte* dstBytes, int srcCount){
  byte overflowByte = 0;
  byte overflowPos = 0;
  int dstPos = 0; //current writing position in dst array
  for(int srcPos = 0; srcPos < srcCount; srcPos++){

    //store msb in overflowByte, filling bits from left, shifting one extra to avoid msb
    overflowByte |= (srcBytes[srcPos] & 0x80) >> (overflowPos + 1); //store msb in overflow byte using next free position
    overflowPos++; //update overflow write position

    //passthrough the 7-bit truncated byte filling destination array from left
    dstBytes[dstPos] = srcBytes[srcPos] & ~0x80; //write the 7 allowed bits (zeroing the msb)
    dstPos++;//update destination write position

    //write overflow byte to stream when it's full or stream is ending
    if(overflowPos == 7 || srcPos == srcCount-1){ //byte full or stream ended
      dstBytes[dstPos] = overflowByte; //write the 7 allowed bits
      dstPos++; //update destination write position
      overflowByte = 0; //reset overflow byte
      overflowPos = 0; //start writing from beginning again
    }
  }
  return dstPos;
}

/** Should be symmetric with encodeTo7(). It populates the specified number of output bytes by reading
* 7 bits from each source byte and retrieving the extra bit from a 7-bit overflow byte which is written after 
* after each frame of 7 bytes (with the final frame potentially being less than 7 bytes). */
void decodeFrom7(byte* srcBytes, byte* dstBytes, int dstCount){
  int srcPos = 0;
  int partialFrameLength = dstCount % 7; //find out number of bytes stored in last frame (remainder from frames of 7)
  //int srcCount = ((dstCount / 7) * 8) + (partialFrameLength == 0 ? 0 : partialFrameLength + 1); //count of source bytes needed
  int overflowPos = 0; //keeps track of the next overflow bit to read from the overflow byte 
  for(int dstPos = 0; dstPos < dstCount; dstPos++){

    //get the 7 bits from the current byte, and reconstruct the final bit from the overflowbyte
    int frameLength = dstPos + partialFrameLength < dstCount ? 7 : partialFrameLength; //frame length (not including overflow byte)
    dstBytes[dstPos] = srcBytes[srcPos] | ((srcBytes[srcPos - overflowPos + frameLength] << (1 + overflowPos)) | 0x80); //read extra overflow bit from predictably offset overflow byte 
                                                                                                      //(srcPos - overflowPos is the start of the frame)
    overflowPos++; //update overflow read position
    srcPos++; //update src read position
    if(overflowPos == 7){
      overflowPos = 0;
      srcPos++; //update read position to skip the overflow byte
    }
  }
}
# returns the bytes encoded see canonical Arduino code for comments - this is a python port
def encode7(srcbytes):

    dstbytes = array()
    overflowbyte = 0
    overflowpos = 0
    dstpos = 0
    for(srcpos, srcbyte in enumerate(srcbytes):
        overflowbyte |= (srcvalues[srcpos] & 0x80) >> (overflowpos + 1)
        overflowpos += 1
    dstbytes.push(srcbytes[srcpos] & ~0x80)
    dstpos += 1

    if(overflowPos == 7 || srcPos == srcCount-1):
        dstbytes.push(overflowbyte);
        dstpos += 1
        overflowbyte = 0
        overflowpos = 0

    return dstbytes

# returns the bytes decoded, see canonical Arduino code for comments - this is a port
def decode7(srcbytes, dstcount):
    dstbytes = array()
    srcpos = 0
    partialframelength = srcbytes.length mod 8
    if(partialframelength != 0):
        partialframelength -= 1

    overflowpos = 0

    for(dstpos in range(dstcount)):
        framelength = 7 if (dstpos + partialframelength < dstcount) else partialframelength 
        dstbytes.push(srcbytes[srcpos] | ((srcbytes[srcpos - overflowpos + framelength] << (1 + overflowpos)) | 0x80))
        overflowpos += 1
        srcpos += 1
        if(overflowpos == 7):
            overflowpos = 0
            srcpos += 1

    return dstbytes

from pyfirmata.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.