MicroMod Beta Testing

I'm playing the FlexIO DMA. Can't seem to get hardware triggering to work, but the DMA does transfer the image if I cheat and manually trigger the DMA channel each time the shifter status flag is set. Going to send a pull request with this work-in-progress DMA code.
 
I'm playing the FlexIO DMA. Can't seem to get hardware triggering to work, but the DMA does transfer the image if I cheat and manually trigger the DMA channel each time the shifter status flag is set. Going to send a pull request with this work-in-progress DMA code.

Merge done.
 
Sent a PR with the work-in-progress DMA code.

https://github.com/mjs513/TMM-HB01B0-Camera/pull/7/files

When you run it, you'll probably see this in the serial monitor

Code:
ERROR: 19764 manual triggers were needed
ERROR: DMA never triggered by hardware!!!

You can see it is transferring the image by DMA, but for reasons I can't understand the hardware trigger from FlexIO to the DMAMUX doesn't seem to work. So I added code which polls the shifter status. If it's seen as needing transfer twice in a row, the DMA channel is manually triggered.

Maybe there's some obscure (or totally obvious) FlexIO setting I've missed somewhere?
 
PR was merged. Just downloaded it and see what you mean. Started reading FlexIO once :) Guess I will have to pull the manual out again.

For some reason having trouble with @defragsters sketch - not sure why so reverted back.

Anyway its looking good so far.
 
Looks like my display woes might be from pulling in the latest ILI9341_t3n. When I run graphicstest from ILI9341_t3, my display works. But graphicstest from ILI9341_t3n now gives a white screen. Later today will try to dig into what changed.
 
Looks like my display woes might be from pulling in the latest ILI9341_t3n. When I run graphicstest from ILI9341_t3, my display works. But graphicstest from ILI9341_t3n now gives a white screen. Later today will try to dig into what changed.
Thats strange, I only get that when my pin assignment is off - know this is going to be a silly question but did you remember (1) to change the pin assignments in the graphicstest, and (2) make sure you have ILI9341 selected in the test sketch. Only saying that because those are the 2 things that always get me :)
 
Morning All,

Will have to play... I did/do have DMA with FlexIO when making a Serial port, for doing RX in the background. May have to compare.

Also once FlexIO is working wonder if we/I should pull out the DMA using GPIO?

I am still curious about why things broke, but...
 
Thats strange, I only get that when my pin assignment is off - know this is going to be a silly question but did you remember (1) to change the pin assignments in the graphicstest, and (2) make sure you have ILI9341 selected in the test sketch. Only saying that because those are the 2 things that always get me :)

Maybe Reset Pin? I will switch back over.
 
@PaulStoffregen
Was going through your DMA code (you guys are bringing me down another rabbit hole with DMA) :)

Anyway think this is the function that controls dma h/w trigger:
Code:
	// Use a hardware trigger to make the DMA channel run
	void triggerAtHardwareEvent(uint8_t source) {
		volatile uint32_t *mux = &DMAMUX_CHCFG0 + channel;
		//mux = (volatile uint32_t *)&(DMAMUX_CHCFG0) + channel;
		*mux = 0;
		*mux = (source & 0x7F) | DMAMUX_CHCFG_ENBL;
	}
especially the last line. Now if I look at pg 84 of the RM it looks like you have to enable the channel (DMAMUX_CHCFG_ENBL) and the trigger(DMAMUX_CHCFG_TRIG). Think the trigger is not getting enabled? Don't know if thats taken care of with source & 0x7F?
 
Morning All,

Will have to play... I did/do have DMA with FlexIO when making a Serial port, for doing RX in the background. May have to compare.

Also once FlexIO is working wonder if we/I should pull out the DMA using GPIO?

I am still curious about why things broke, but...

Think I agree - doesn't make sense to keep DMA using GPIO. To be honest I would hold off on trying to get it working with GPIO for the HM01b0
 
Think I agree - doesn't make sense to keep DMA using GPIO. To be honest I would hold off on trying to get it working with GPIO for the HM01b0
:eek: ;) - That way I can pack up my bags and go home :D

Will stash my changes in holding area and probably expunge.

Edit: Forgot to mention, it is working on my ILI9341...
 
:eek: ;) - That way I can pack up my bags and go home :D

Will stash my changes in holding area and probably expunge.

Edit: Forgot to mention, it is working on my ILI9341...

As they say keep dreaming :)

Just tried it on the ST7789 and seems to be working there as well. Although trying to use for video don't work too well. Works a bit better on 9341. Think maybe it will work better when h/w trig gets sorted out (for pseudo video that is)
 
@all just pushed the WIP stuff for DMA up to new branch dma_full_sensor

Still not fully working with the full frame 324x244 things are out of sync... Will play a little more, will pull most out of main branch.

While Playing with it I added a new command '?' which walks through a frame and sees how many hrefs and pckls...

Code:
typedef struct {
    uint32_t frameTimeMicros;
    uint16_t vsyncStartCycleCount;
    uint16_t vsyncEndCycleCount;
    uint16_t hrefCount;
    uint32_t cycleCount;
    uint16_t pclkCounts[350]; // room to spare.
    uint16_t pclkNoHrefCount;
} frameStatics_t;

frameStatics_t fstat;

void HM01B0::captureFrameStatistics()
{
   memset((void*)&fstat, 0, sizeof(fstat));

   // lets wait for the vsync to go high;
    while ((*_vsyncPort & _vsyncMask) != 0); // wait for HIGH

    // now lets wait for it to go low    
    while ((*_vsyncPort & _vsyncMask) == 0) fstat.vsyncStartCycleCount ++; // wait for LOW

    while ((*_hrefPort & _hrefMask) == 0); // wait for HIGH
    while ((*_pclkPort & _pclkMask) != 0); // wait for LOW

    uint32_t microsStart = micros();
    // now loop through until we get the next _vsynd
    // BUGBUG We know that HSYNC and PCLK on same GPIO VSYNC is not...
    uint32_t regs_prev = 0;
    noInterrupts();
    while ((*_vsyncPort & _vsyncMask) != 0) {

        fstat.cycleCount++;
        uint32_t regs = (*_hrefPort & (_hrefMask | _pclkMask ));
        if (regs != regs_prev) {
            if ((regs & _hrefMask) && ((regs_prev & _hrefMask) ==0)) fstat.hrefCount++;
            if ((regs & _pclkMask) && ((regs_prev & _pclkMask) ==0)) fstat.pclkCounts[fstat.hrefCount]++;
            if ((regs & _pclkMask) && ((regs_prev & _hrefMask) ==0)) fstat.pclkNoHrefCount++;
            regs_prev = regs;
        }
    }
    while ((*_vsyncPort & _vsyncMask) == 0) fstat.vsyncEndCycleCount++; // wait for LOW
    interrupts();
    fstat.frameTimeMicros = micros() - microsStart;

    // Maybe return data. print now
    Serial.printf("*** Frame Capture Data: elapsed Micros: %u loops: %u\n", fstat.frameTimeMicros, fstat.cycleCount);
    Serial.printf("   VSync Loops Start: %u end: %u\n", fstat.vsyncStartCycleCount, fstat.vsyncEndCycleCount);
    Serial.printf("   href count: %u pclk ! href count: %u\n    ", fstat.hrefCount,  fstat.pclkNoHrefCount);
    for (uint16_t ii=0; ii < fstat.hrefCount + 1; ii++) {
        Serial.printf("%3u ", fstat.pclkCounts[ii]);
        if (!(ii & 0x0f)) Serial.print("\n    ");
    }
    Serial.println();
}

Output looks correct:
Code:
*** Frame Capture Data: elapsed Micros: 104 loops: 694041
   VSync Loops Start: 48116 end: 48118
   href count: 244 pclk ! href count: 1
      0 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 324 
    324 324 324 324
Although it did see one PCLK without the HREF bit being set...
 
PR was merged. Just downloaded it and see what you mean. Started reading FlexIO once :) Guess I will have to pull the manual out again.

For some reason having trouble with @defragsters sketch - not sure why so reverted back.

Anyway its looking good so far.

What 'trouble'? Only change is to add 'F'?

As noted some starts get odd sync on timing, but restart works 'most times' - with the way it was.

Also noted 'F' MovieMode seems timing race dependent. I did not note after doing the updateScreenAsync() an added a "delay(1)" thinking FlexIO was coming back around updating imageBuffer before the screen was updated and that gave a HORRID rolling 'Movie Mess'. Then adding the 'Complete' test was as bad or worse.

@KurtE is the updateScreenAsync() the best way to know the 9341 code is done writing for getting image sync? for some reason it cause 'loss of 5-6' fps - and then the image would never sync.

The FlexIO 'F' movieMode was left running during 6-7 hours time since last post and no troubles as it was still active. Only diff is sunlight in window behind me filling background center with sunlight and image corners looking a bit darker i.e. with vignetting - but image does auto bright adjust.

Also just noting TFT image is no longer in 'Selfie/Mirror' mode - the image has flipped to 'Camera' mode.

Hope you guys are enjoying the rabbit holes :)
 
@defragster
Think I was running into the problems you just described plus issues with the display connections.

Also I changed the "F" movie function to this
Code:
  if ( g_continuous_flex_mode )
   {
      memset((uint8_t*)frameBuffer, 0, sizeof(frameBuffer));
      hm01b0.set_mode(HIMAX_MODE_STREAMING_NFRAMES, 1);
      hm01b0.readFrameFlexIO(frameBuffer);
      //Serial.println("Finished reading frame"); Serial.flush();
      //convert grayscale to rgb
      //for(int i = 0; i < FRAME_HEIGHT*FRAME_WIDTH; i++) {
      //  imageBuffer[i] = color565(frameBuffer[i], frameBuffer[i], frameBuffer[i]);
      //}
      //tft.writeSubImageRect(0, 0, tft.width(), tft.height(),  (FRAME_WIDTH - tft.width()) / 2, (FRAME_HEIGHT - tft.height()),
      //                    FRAME_WIDTH, FRAME_HEIGHT, imageBuffer);
        tft.setOrigin(-2, -2);
        tft.writeRect8BPP(0, 0, FRAME_WIDTH, FRAME_HEIGHT, frameBuffer, mono_palette);
        tft.setOrigin(0, 0);
      tft.updateScreenAsync();
    }
 
Will have to play... I did/do have DMA with FlexIO when making a Serial port, for doing RX in the background. May have to compare.

Hope you can find whatever I missed on the FlexIO hardware trigger. It's probably something "trivial" I overlooked.


Also once FlexIO is working wonder if we/I should pull out the DMA using GPIO?

I wouldn't toss that code! It still could be really useful on Teensy 4.1 where we don't have 8 contiguous FlexIO1 or FlexIO2 pins.
 
@defragster
Think I was running into the problems you just described plus issues with the display connections.

Also I changed the "F" movie function to this
...

First time I uploaded that Change - from how Paul wrote the rectangle I got tearing.

Two uploads after that and then a Reset - all came up with good movie in perfect Sync and seeing the 31 fps - with a pulsing dark video from updates.

NICE the for() moving frameBuffer to imageBuffer not needed!
 
@defragster
Also think the timing prints were getting me confused. Also playing with some settings for brightness and exposure. With the lights on my image tended to be basically showing glare. Went to the openmv forum and found a good setting to start if you want to play - not sure we need that calAE function call:
Code:
  hm01b0.set_brightness(1);
  hm01b0.set_auto_exposure(true, 1750);  //higher the setting the less saturaturation of whiteness
  hm01b0.cmdUpdate();  //only need after changing auto exposure settings
At least now I can see a descent image in bright light :)

EDIT: Ok think I am going to go with these if there is alot of light
Code:
  hm01b0.set_gainceiling(GAINCEILING_2X);
  /* Brightness
   *  Can be 1, 2, or 3
   */
  hm01b0.set_brightness(3);
  hm01b0.set_auto_exposure(true, 1500);  //higher the setting the less saturaturation of whiteness
  hm01b0.cmdUpdate();  //only need after changing auto exposure settings
 
Hope you can find whatever I missed on the FlexIO hardware trigger. It's probably something "trivial" I overlooked.

I wouldn't toss that code! It still could be really useful on Teensy 4.1 where we don't have 8 contiguous FlexIO1 or FlexIO2 pins.

Set up releases for the library and that code is permanently there as Release v1.0.0. The flexIO changes will be in v1.1 I guess. Just trying to keep what works.
 
@defragster
Also think the timing prints were getting me confused. Also playing with some settings for brightness and exposure. With the lights on my image tended to be basically showing glare. Went to the openmv forum and found a good setting to start if you want to play - not sure we need that calAE function call:
...
At least now I can see a descent image in bright light :)

Added those three lines in setup() ? - I don't see a diff - maybe? There is good detail now I may not have seen before with a sun bright window backlighting me - about 1/4 of the screen is white wash from window and ceiling.

If I pick up my tea mug from beside camera as brought to drink is blocks the window backlight and the image brightness comes up not having to average out the window and bright ceiling over the window

'timing prints'? the one second print? If the 'i' info hadn't gotten lost I could have used that timer and enable disable prints - but didn't bother to restore that and just did that elapsedMillis() version in place
 
@defragster
Going to put the timings back in since I know what to expect now.

Was driving me crazy when it FPS going down to 16 but think that was display connection issue
 
@defragster
Going to put the timings back in since I know what to expect now.

Was driving me crazy when it FPS going down to 16 but think that was display connection issue

It could save 'lastFPS' and only print on change to stop the 1Hz spew.

I just took out the 3 p#395 lines and it seems I have better contrast to the white spots on my dark shirt. Then put them back and got 3 of 4 bad starts? Then removed them and white is still good and 3 out of 3 upload/Reset came up without video image problems?
 
@Paul - @KurtE
The more I read the more confused I get. Was looking at AN12686, pg13 and what @KurtE was DMA stuff. On pg 13 for DMA setup the last 2 bullets:
Code:
• Last destination address adjustment: 0, which means no adjustment. The new destination address is configured in the
VSYNC ISR.
• Disable the DMA request after each major loop. The request is enabled in the VSYNC ISR each time.
which kind of matches what Kurt had in his DMA setup code:
Code:
  _dmachannel.attachInterrupt(dmaInterrupt);

So don't need it with FlexIO? Just a question. ---- EDIT3 - Never mind read a bit more in Chapter 4 and DMA.

EDIT: Came across this thread https://forum.pjrc.com/threads/63353-Teensy-4-1-How-to-start-using-DMA?highlight=dma+trigge that I am in the process of trying to sort out in my head.

EDIT2: Where is the trig enabled in the code? - see post #386. "source & 0x7F" enables the trigger?
 
Last edited:
Back
Top