Menu

READ ACCELEROMETER MMA8452

Help
2023-01-08
2023-02-14
<< < 1 2 (Page 2 of 2)
  • Anobium

    Anobium - 2023-01-13

    We should take this thread to the developer section of the forum ?

    Well. I just got back and here is an update.

    I have a added the first pass approach the converter and I have added a handler to process CPP different from .H ( this is to improve performance and make the code easier to maintain).

    The new converter now creates the output shown below!

    I will explain. The coverter is going thru and finding (at the moment) just the BOOL method(s). When it find a BOOL method it processes the BOOL method counting "{" or "}". This counting like this finds the end of the method. It then marks the code as PRESERVED. If line is PRESERVED then on later processes does not reprocess the line again.

    So, as you can see the raw C code is now shown. So, what is the ;?F3L21S0? - these are File number, Line number and Subroutine number, We will need this metadata later when we start to look for calls to subroutines. Metadata can be used and then removed later.

    Already, you can see the structure of the code, some the logic and it you see the core C code. And, think of two copies of the C code - for each line there is 1) A copy that is changed as we process, and,2) a copy that has the original line plus the metadata (the master code).

    Current command line - now includes CPP file. The order of the files on the command line is not important.

    gawk -f ctogcb.awk max30100.h MAX30100_Registers.h max30100.cpp

    Enjoy

    //  method BEGIN
    {;?F3L20S0?
        Wire.begin();;?F3L21S0?
        Wire.setClock(I2C_BUS_SPEED);;?F3L22S0?
        if (getPartId() != EXPECTED_PART_ID) {;?F3L23S0?
            return false;;?F3L24S0?
        };?F3L25S0?
        setMode(DEFAULT_MODE);;?F3L26S0?
        setLedsPulseWidth(DEFAULT_PULSE_WIDTH);;?F3L27S0?
        setSamplingRate(DEFAULT_SAMPLING_RATE);;?F3L28S0?
        setLedsCurrent(DEFAULT_IR_LED_CURRENT, DEFAULT_RED_LED_CURRENT);;?F3L29S0?
        setHighresModeEnabled(true);;?F3L30S0?
        return true;;?F3L31S0?
    };?F3L32S0?
    
    //  method GETRAWVALUES
    //  parameters UINT16_T *IR, UINT16_T *RED
    {;?F3L65S0?
        if (!readoutsBuffer.isEmpty()) {;?F3L66S0?
            SensorReadout readout = readoutsBuffer.pop();;?F3L67S0?
            *ir = readout.ir;;?F3L68S0?
            *red = readout.red;;?F3L69S0?
            return true;;?F3L70S0?
        } else {;?F3L71S0?
            return false;;?F3L72S0?
        };?F3L73S0?
    };?F3L74S0?
    
    //  method ISTEMPERATUREREADY
    {;?F3L129S0?
        return !(readRegister(MAX30100_REG_MODE_CONFIGURATION) & MAX30100_MC_TEMP_EN);;?F3L130S0?
    };?F3L131S0?
    

    Why use the funny metaadata ? This is the same method as the GCBASIC compiler uses and that works very nicely.

    Why use PRESERVED ? This is the same method as the GCBASIC compiler uses and that works very nicely.

     

    Last edit: Anobium 2023-01-13
  • Anobium

    Anobium - 2023-01-14

    I have refactored the converter to now handle all type of C methods, and, to output to the command/terminal window and output the 'converted' code to OUTPUT.GCB

    Command line is: cls&gawk -f ctogcb.awk MAX30100.h MAX30100_Registers.h MAX30100.cpp

    OUTPUT.GCB as all the constants and code as show below.

    // C to GCB Conversion vv0.9a 2023
    
    #DEFINE DEFAULT_MODE                MAX30100_MODE_HRONLY
    #DEFINE DEFAULT_SAMPLING_RATE       MAX30100_SAMPRATE_100HZ
    #DEFINE DEFAULT_PULSE_WIDTH         MAX30100_SPC_PW_1600US_16BITS
    #DEFINE DEFAULT_RED_LED_CURRENT     MAX30100_LED_CURR_50MA
    ... etc lot of them..
    // PART ID REGISTER
    #DEFINE MAX30100_REG_PART_ID                    0XFF
    #DEFINE MAX30100_FIFO_DEPTH                     0X10
    
    
    //***********************************************************
    //Code section
    
    bool MAX30100::begin();?F3L27S1?
    {;?F3L28S1?
        Wire.begin();;?F3L29S1?
        Wire.setClock(I2C_BUS_SPEED);;?F3L30S1?
        if (getPartId() != EXPECTED_PART_ID) {;?F3L32S1?
            return false;;?F3L33S1?
        };?F3L34S1?
        setMode(DEFAULT_MODE);;?F3L36S1?
        setLedsPulseWidth(DEFAULT_PULSE_WIDTH);;?F3L37S1?
        setSamplingRate(DEFAULT_SAMPLING_RATE);;?F3L38S1?
        setLedsCurrent(DEFAULT_IR_LED_CURRENT, DEFAULT_RED_LED_CURRENT);;?F3L39S1?
        setHighresModeEnabled(true);;?F3L40S1?
        return true;;?F3L42S1?
    };?F3L43S1?
    void MAX30100::setMode(Mode mode);?F3L45S4?
    ... lots of code
    

    Terminal now shows information.

    Find BOOL methods
        Found method BEGIN()
        Found method GETRAWVALUES(UINT16_T *IR, UINT16_T *RED)
        Found method ISTEMPERATUREREADY()
    
    Find VOID methods
        Found method SETMODE(MODE MODE)
        Found method SETLEDSPULSEWIDTH(LEDPULSEWIDTH LEDPULSEWIDTH)
        Found method SETSAMPLINGRATE(SAMPLINGRATE SAMPLINGRATE)
        Found method SETLEDSCURRENT(LEDCURRENT IRLEDCURRENT, LEDCURRENT REDLEDCURRENT)
        Found method SETHIGHRESMODEENABLED(BOOL ENABLED)
        Found method UPDATE()
        Found method RESETFIFO()
        Found method WRITEREGISTER(UINT8_T ADDRESS, UINT8_T DATA)
        Found method BURSTREAD(UINT8_T BASEADDRESS, UINT8_T *BUFFER, UINT8_T LENGTH)
        Found method READFIFODATA()
        Found method STARTTEMPERATURESAMPLING()
        Found method SHUTDOWN()
        Found method RESUME()
    
    Find UINT8_T methods
        Found method READREGISTER(UINT8_T ADDRESS)
        Found method GETPARTID()
    
    Find FLOAT methods
        Found method RETRIEVETEMPERATURE()
    
    Found methods as follows:
    BEGIN
    GETRAWVALUES
    ISTEMPERATUREREADY
    SETMODE
    SETLEDSPULSEWIDTH
    SETSAMPLINGRATE
    SETLEDSCURRENT
    SETHIGHRESMODEENABLED
    UPDATE
    RESETFIFO
    WRITEREGISTER
    BURSTREAD
    READFIFODATA
    STARTTEMPERATURESAMPLING
    SHUTDOWN
    RESUME
    READREGISTER
    GETPARTID
    RETRIEVETEMPERATURE
    

    So, now to the interesting bit to start processing all the code. The approach will be again very similar to GCBASIC compiler. Find and process things in order to convert the code.

         Compile FOR commands
         Compile If(s)
         Compile While
         Compile Wire. commands
         Compile Floats usingfactorisation
         Comple  Mathematical Logic 
         Compile Exit methods
         Compile Return
         Add variable(s) and bit(s)
         Tidy Operations
          Flag uncompiled code
    

    Easy

     
  • Anobium

    Anobium - 2023-01-16

    @mmotte

    A progress update. The latest attachment is now generating GCB code for specific case. I have added the processing for C IF staements.

    The IF handler. Support single and multiple lines IFs an IF-ELSE again with single and multiple lines statements.

    The processing now has a reusable function called findnextmatchingRbraces() where you get back the pointer to the next matched brace. Which essentially means the converter knows where to place the GCB code.

    Examples follow but this new converter code means that you now take a specific function and work in on independently - Compile Wire. commands for instance. I will do WHILE and FOR-NEXT next.

    The converter now outputs messages to the terminal and an OUTPUT.GCB file and UNPROCESSED.CPP file. They contain the coverted file and stuff the converter cannot handle.

    Enjoy


    Example 1

        if (getPartId() != EXPECTED_PART_ID) 
            return false;
    
        if (getPartId() != EXPECTED_PART_ID) {
            return false;
        }
    

    To GCB Code - ignore the Original coding as this will be removed later.
    Note. To maintain line numbering that in some cases the multiline GCB seperator is needed.

    If GETPARTID()!=EXPECTEDPARTID Then;;?F3L32S1?
            RETURN FALSE:End if;;?F3L33S1?
    If GETPARTID()!=EXPECTEDPARTID Then;;?F3L35S1?
            return false;;?F3L36S1?
    End if;?F3L37S1?
    

    Example 2

        if (enabled) {
            writeRegister(MAX30100_REG_SPO2_CONFIGURATION, previous | MAX30100_SPC_SPO2_HI_RES_EN);
        } else {
            writeRegister(MAX30100_REG_SPO2_CONFIGURATION, previous & ~MAX30100_SPC_SPO2_HI_RES_EN);
        }
    

    To GCB Code

    If ENABLED Then;;?F3L73S8?
            writeRegister(MAX30100_REG_SPO2_CONFIGURATION, previous | MAX30100_SPC_SPO2_HI_RES_EN);;?F3L74S8?
    Else;?F3L75S8?
            writeRegister(MAX30100_REG_SPO2_CONFIGURATION, previous & ~MAX30100_SPC_SPO2_HI_RES_EN);;?F3L76S8?
    End if;;?F3L77S8?
    

    Example 3

        if (!readoutsBuffer.isEmpty()) {
            SensorReadout readout = readoutsBuffer.pop();
    
            *ir = readout.ir;
            *red = readout.red;
    
            return true;
        } else {
            return false;
        }
    }
    

    To GCB Code. The READOUTSBUFFER.ISEMPTY() and the pointers will be resolved later as the convertor is developed.

    If !READOUTSBUFFER.ISEMPTY() Then;;?F3L87S2?
            SensorReadout readout = readoutsBuffer.pop();;?F3L88S2?
            *ir = readout.ir;;?F3L90S2?
            *red = readout.red;;?F3L91S2?
            return true;;?F3L93S2?
    Else;?F3L94S2?
            return false;;?F3L95S2?
    End if;;?F3L96S2?
    

    Example 4

        if (toRead) {
            burstRead(MAX30100_REG_FIFO_DATA, buffer, 4 * toRead);
    
            for (uint8_t i=0 ; i < toRead ; ++i) {
                // Warning: the values are always left-aligned 
                readoutsBuffer.push({
                        .ir=(uint16_t)((buffer[i*4] << 8) | buffer[i*4 + 1]),
                        .red=(uint16_t)((buffer[i*4 + 2] << 8) | buffer[i*4 + 3])});
            }
        }
    

    To GCB Code. The READOUTSBUFFER.ISEMPTY() and the pointers will be resolved later as the convertor is developed.

    If TOREAD Then;;?F3L144S13?
            burstRead(MAX30100_REG_FIFO_DATA, buffer, 4 * toRead);;?F3L145S13?
            for (uint8_t i=0 ; i < toRead ; ++i) {;?F3L147S13?
                // Warning: the values are always left-aligned ;?F3L148S13?
                readoutsBuffer.push({;?F3L149S13?
                        .ir=(uint16_t)((buffer[i*4] << 8) | buffer[i*4 + 1]),;?F3L150S13?
                        .red=(uint16_t)((buffer[i*4 + 2] << 8) | buffer[i*4 + 3])});;?F3L151S13?
            };?F3L152S13?
    End if;?F3L153S13?
    

    Same commandline: cls&gawk -f ctogcb.awk MAX30100.h MAX30100_Registers.h MAX30100.cpp

    See AWK attached.

     
  • Anobium

    Anobium - 2023-01-16

    Just added C While() functional syntax. Now the basic conversion routines are working - it is a lot faster.

        while (Wire.available()) {
            buffer[idx++] = Wire.read();
        }
    
        Do {
            buffer[idx++] = Wire.read();
        } 
        while (Wire.available())
    

    to GCB follows. This uses GCBASIC line concat to maintain the lines of code.

            Do While(WIRE.AVAILABLE());
                buffer[idx++] = Wire.read();
            Loop;
            DO;
                buffer[idx++] = Wire.read();
            Loop _ 
            while (Wire.available())
    
     

    Last edit: Anobium 2023-01-16
  • Anobium

    Anobium - 2023-01-17

    Just updated to add I2C, variable management and top and tail methods.

    Only parameters to complete.

    Examples:

    void MAX30100::burstRead(uint8_t baseAddress, uint8_t *buffer, uint8_t length)
    {
        Wire.beginTransmission(MAX30100_I2C_ADDRESS);
        Wire.write(baseAddress);
        Wire.endTransmission(false);
        Wire.requestFrom((uint8_t)MAX30100_I2C_ADDRESS, length);
    
        uint8_t idx = 0;
        while (Wire.available()) {
            buffer[idx++] = Wire.read();
        }
    }
    

    Converted to ( note the paramteters are not converted.

        Sub BURSTREAD(UINT8_T BASEADDRESS, UINT8_T *BUFFER, UINT8_T LENGTH)
    
        // removed by conversion - WIRE.BEGINTRANSMISSION(MAX30100_I2C_ADDRESS)
        HI2CSTART: HI2CSEND(BASEADDRESS)
        HI2CRESTART: HI2CSEND(MAX30100_I2C_ADDRESS)
        Dim IDX As Byte: IDX = 0
        DIM IDX AS BYTE:IDX=0:  Do While(IDX<LENGTH);
        HI2CRECEIVE(BUFFER[IDX], ACK ) : idx++
            Loop;
        End Sub
    

    This is an example of conversion. The only change to make this work would be to change UINT8_T BASEADDRESS, UINT8_T *BUFFER, UINT8_T LENGTH to BASEADDRESS, BUFFER() , LENGTH the parameters,

    Whilst no converter will be perfect this will convert almost all the code. There will be many conditions to be added or sorted but not to shabby for a few hours.

    Enjoy

     
  • Anobium

    Anobium - 2023-01-17

    A program using the converted code. I have created a test program (actually this is the first I have every tried I was just reviewing in the editor prior to this test).

    It compiles. After adding HWI2C and the required variables and constants.

    :=)

     
  • Anobium

    Anobium - 2023-01-19

    The latest CtoGCBASIC converter. It is pretty good.

    This version has improvements to the quality of the conversion. I have rewritten the pattern matching routines to improve the ability to recognise all the code.

    The process output two files - OUTFILE.GCB and UNPROCESSED.GCB - the terminal window will issue warnings specifically to I2C handling with recommendations on resolution in the OUTFILE.GCB

    Example of code:

    C source

    void MAX30100::resetFifo()
    {
        writeRegister(MAX30100_REG_FIFO_WRITE_POINTER, 0);
        writeRegister(MAX30100_REG_FIFO_READ_POINTER, 0);
        writeRegister(MAX30100_REG_FIFO_OVERFLOW_COUNTER, 0);
    }
    
    uint8_t MAX30100::readRegister(uint8_t address)
    {
        Wire.beginTransmission(MAX30100_I2C_ADDRESS);
        Wire.write(address);
        Wire.endTransmission(false);
        Wire.requestFrom(MAX30100_I2C_ADDRESS, 1);
    
        return Wire.read();
    }
    

    GCBASIC

        SUB RESETFIFO()
            WRITEREGISTER(MAX30100_REG_FIFO_WRITE_POINTER, 0);
            WRITEREGISTER(MAX30100_REG_FIFO_READ_POINTER, 0);
            WRITEREGISTER(MAX30100_REG_FIFO_OVERFLOW_COUNTER, 0);
        END SUB
        FUNCTION READREGISTER(UINT8_T ADDRESS) AS BYTE
        // REMOVED BY CONVERSION - WIRE.BEGINTRANSMISSION(MAX30100_I2C_ADDRESS)
        HI2CSTART: HI2CSEND(ADDRESS)
        HI2CRESTART
        HI2CSEND(MAX30100_I2C_ADDRESS)
        HI2CRECEIVE ( I2CBYTE): READREGISTER = I2CBYTE: HI2CSTOP
        END FUNCTION
        SUB WRITEREGISTER(UINT8_T ADDRESS, UINT8_T DATA)
        // REMOVED BY CONVERSION - WIRE.BEGINTRANSMISSION(MAX30100_I2C_ADDRESS)
        HI2CSTART: HI2CSEND(ADDRESS)
        HI2CSEND(DATA)
        HI2CSTOP
        END SUB
    

    The code is acceptable. As this is very close to a full conversion.

    The outstanding change is to improve the parameters in the methode definitions but this can wait till next week.

    Enjoy

     
  • Anobium

    Anobium - 2023-01-19

    The terminal looks like this ... not to confusing.

    Terminal Windows

     

    Last edit: Anobium 2023-01-19
  • Anobium

    Anobium - 2023-01-20

    I have put some code through the converter and Angel is loading the converter onto the GCBASIC website so you can drag files in, and, get them converted from C to GCBASIC.

    Insights:

    1. There are commands and variables that are not permitted by GCBASIC compiler and/or MPASM. This is important. C naming permits the use of sub routines like Shutdown() and variables like Data or Address. All of these are reserved words. There will be more like this. So, the converter will flag these and convert the code. The user will have to resolve as the converter would be guessing to change the names of any object.
    2. Floats are permitted in C. The converter will comment out all code within a float method. The user will have to resolve using factorization.
    3. C creates and uses local variables. There will be a need to move array definitions from the subs and/or functions to main user program.
    4. The files created are all in upper case and the indents are not corrected. The user will have to resolve.
    5. The converter uses GCBASIC multiline coding styles ( for specific conversions ). The user will have to adapt the converted code to move code to a single - only needed to make it look nice. The is no function difference either way.

    When Angel creates the converter Web page. This thread will cease. And, any issue should reported via the GCBASIC issue tracker.


    Meanwhile... it is very cool to see it work!!

     
  • William Roth

    William Roth - 2023-01-20

    Lots of hard work and progress. Thanks Evan.

     
  • Anobium

    Anobium - 2023-01-22

    If only... I had done this a few years ago...

    An example SDDD1306.CPP from GitHub.

    This was 99% completly converted. Minor editing needed in a for-next statement! Clearly the I2C commands would need updating but this would be a great start for anyone.

    I impressed myself.

    Evan

    // C to GCB Conversion vv0.9a 2023
    
    #DEFINE SSD1306_DEFAULT_ADDRESS 0X78
    #DEFINE SSD1306_SETCONTRAST 0X81
    #DEFINE SSD1306_DISPLAYALLON_RESUME 0XA4
    #DEFINE SSD1306_DISPLAYALLON 0XA5
    #DEFINE SSD1306_NORMALDISPLAY 0XA6
    #DEFINE SSD1306_INVERTDISPLAY 0XA7
    #DEFINE SSD1306_DISPLAYOFF 0XAE
    #DEFINE SSD1306_DISPLAYON 0XAF
    #DEFINE SSD1306_SETDISPLAYOFFSET 0XD3
    #DEFINE SSD1306_SETCOMPINS 0XDA
    #DEFINE SSD1306_SETVCOMDETECT 0XDB
    #DEFINE SSD1306_SETDISPLAYCLOCKDIV 0XD5
    #DEFINE SSD1306_SETPRECHARGE 0XD9
    #DEFINE SSD1306_SETMULTIPLEX 0XA8
    #DEFINE SSD1306_SETLOWCOLUMN 0X00
    #DEFINE SSD1306_SETHIGHCOLUMN 0X10
    #DEFINE SSD1306_SETSTARTLINE 0X40
    #DEFINE SSD1306_MEMORYMODE 0X20
    #DEFINE SSD1306_COLUMNADDR 0X21
    #DEFINE SSD1306_PAGEADDR   0X22
    #DEFINE SSD1306_COMSCANINC 0XC0
    #DEFINE SSD1306_COMSCANDEC 0XC8
    #DEFINE SSD1306_SEGREMAP 0XA0
    #DEFINE SSD1306_CHARGEPUMP 0X8D
    #DEFINE SSD1306_SWITCHCAPVCC 0X2
    #DEFINE SSD1306_NOP 0XE3
    #DEFINE SSD1306_WIDTH 128
    #DEFINE SSD1306_HEIGHT 64
    #DEFINE SSD1306_BUFFERSIZE (SSD1306_WIDTH*SSD1306_HEIGHT)/8
    
    // Variables and variable type defined and used
    //
    //     C variable/enum type          GCBASIC type 
    //     BYTE                          BYTE
    //     BOOL                          BYTE
    //     UINT16_T                      WORD
    //     UINT8_T                       BYTE
    
    
    //*****************PROCESSED******************************************
    
    
        SUB SSD1306() 
        HI2CINIT(SSD1306_DEFAULT_ADDRESS)
            SENDCOMMAND(SSD1306_DISPLAYOFF)
            SENDCOMMAND(SSD1306_SETDISPLAYCLOCKDIV)
            SENDCOMMAND(0X80)
            SENDCOMMAND(SSD1306_SETMULTIPLEX)
            SENDCOMMAND(0X3F)
            SENDCOMMAND(SSD1306_SETDISPLAYOFFSET)
            SENDCOMMAND(0X00)
            SENDCOMMAND(SSD1306_SETSTARTLINE | 0X00)
            SENDCOMMAND(SSD1306_CHARGEPUMP)
            SENDCOMMAND(0X14)
            SENDCOMMAND(SSD1306_MEMORYMODE)
            SENDCOMMAND(0X00)
            SENDCOMMAND(SSD1306_SEGREMAP | 0X1)
            SENDCOMMAND(SSD1306_COMSCANDEC)
            SENDCOMMAND(SSD1306_SETCOMPINS)
            SENDCOMMAND(0X12)
            SENDCOMMAND(SSD1306_SETCONTRAST)
            SENDCOMMAND(0XCF)
            SENDCOMMAND(SSD1306_SETPRECHARGE)
            SENDCOMMAND(0XF1)
            SENDCOMMAND(SSD1306_SETVCOMDETECT)
            SENDCOMMAND(0X40)
            SENDCOMMAND(SSD1306_DISPLAYALLON_RESUME)
            SENDCOMMAND(SSD1306_NORMALDISPLAY)
            SENDCOMMAND(SSD1306_DISPLAYON)
        END SUB
        SUB SENDCOMMAND(COMMAND) AS BYTE) 
        HI2CSTART()
        HI2CSEND(0X00)
        HI2CSEND(COMMAND)
        HI2CSTOP()
        END SUB
        SUB INVERT(INVERTED) AS BYTE) 
        IF INVERTED THEN
                SENDCOMMAND(SSD1306_INVERTDISPLAY)
            ELSE
                SENDCOMMAND(SSD1306_NORMALDISPLAY)
        END IF
        END SUB
        SUB SENDFRAMEBUFFER(BUFFER) AS BYTE) 
            SENDCOMMAND(SSD1306_COLUMNADDR)
            SENDCOMMAND(0X00)
            SENDCOMMAND(0X7F)
            SENDCOMMAND(SSD1306_PAGEADDR)
            SENDCOMMAND(0X00)
            SENDCOMMAND(0X07)
        DIM PACKET AS BYTE: FOR  PACKET=0 TO 64-1 STEP 1
            HI2CSTART()
            HI2CSEND(0X40)
                DIM PACKET_BYTE AS BYTE: FOR  PACKET_BYTE=0 TO 16-1 STEP 1
                    HI2CSEND(BUFFER(PACKET*16+PACKET_BYTE))
                NEXT
            HI2CSTOP()
            NEXT
        END SUB
    
     

    Last edit: Anobium 2023-01-22
  • ToniG

    ToniG - 2023-02-14

    Converted a few .ino to GCB lately,
    Arduino coders - to set/clear a register bit, tend to like using shifting a bit into position using the register bit name as a constant eg.[mega328] ADCSRB = (0 << ACME) where ACME is bit 6
    GCbasic... ADCSRB.6 = 0
    So need to check the bitname position in mega328.dat file. "ACME,ADCSRB,6"
    As the chip-name is not defined in .ino code like GCbasic maybe some method of input the chip-name for convert .ino -> .gcb might be helpful.

     
    • Anobium

      Anobium - 2023-02-14

      Good idea. The script will be on the website soon. One of the key parameters will have to be the chip name - you raise a great point.

       
<< < 1 2 (Page 2 of 2)

Log in to post a comment.