MicroMod Beta Testing

Created /mjs513/TMM-HB01B0-Camera/pull/10 for adding hm01b0_testv3.ino for posts noted above

Morning all - just having first cup of coffee.

Did the merge for v3 test sketch haven't had a chance to check it out yet. After I read the post of tearing in post I can't seem to duplicate it either using "f"rame or "F" continuous modes. I do have the Sparkfun config commented out and running a frame rate of 30fps. Here's a typical screenshot from the ST7789:
IMG-0346.png

Going to see what your "z" command is doing now :)
 
Just wanted to ask which buffers are really meant to be DMAMEM vs DTCM?

I see this in the examples.

Code:
uint8_t frameBuffer[(324) * 244];
uint16_t imageBuffer[(324) * 244]; DMAMEM
uint8_t sendImageBuf[(324) * 244 * 2];
uint8_t frameBuffer2[(324) * 244] DMAMEM;

Because DMAMEM is after the semicolon on the 2nd line, it will actually apply to the 3rd line.

Either way, the examples should probably get a little cleanup. If the 2nd line was meant to be in DMAMEM, the semicolon should move. If the 3rd line is really meant to be DMAMEM, then it should be on that line so the code is readable.
 
My guess is that its suppose to be on the imageBuffer since its being used for DMA along with frameBuffer2.
 
@KurtE - just noticed I am getting a warning message:
Code:
D:\Users\Merli\Documents\Arduino\hm01b0_testv2\hm01b0_testv2.ino:360:85: warning: invalid conversion from 'void (*)(void*)' to 'bool (*)(void*)' [-fpermissive]
             hm01b0.startReadFrameDMA(&hm01b0_dma_callback, frameBuffer, frameBuffer2);            Serial.println("*** Return from startReadFrameDMA ***");
                                                                                     ^
In file included from D:\Users\Merli\Documents\Arduino\hm01b0_testv2\hm01b0_testv2.ino:25:0:
D:\Users\Merli\Documents\Arduino\libraries\TMM-HM01B0\src/HM01B0.h:134:7: note:   initializing argument 1 of 'bool HM01B0::startReadFrameDMA(bool (*)(void*), uint8_t*, uint8_t*)'
  bool startReadFrameDMA(bool (*callback)(void *frame_buffer)=nullptr, uint8_t *fb1=nullptr, uint8_t *fb2=nullptr);
 
Just wanted to ask which buffers are really meant to be DMAMEM vs DTCM?

I see this in the examples.

Code:
uint8_t frameBuffer[(324) * 244];
uint16_t imageBuffer[(324) * 244]; DMAMEM
uint8_t sendImageBuf[(324) * 244 * 2];
uint8_t frameBuffer2[(324) * 244] DMAMEM;

Because DMAMEM is after the semicolon on the 2nd line, it will actually apply to the 3rd line.

Either way, the examples should probably get a little cleanup. If the 2nd line was meant to be in DMAMEM, the semicolon should move. If the 3rd line is really meant to be DMAMEM, then it should be on that line so the code is readable.
Morning all,

Not fully awake yet, nor had coffee,

We need to go through and maybe remove several of those buffers. Especially the uint16_t one that may not be used anymore as we don't convert from 8 bits to 16 bits...
Also should look at the sendImage stuff to see again to see if we can combine some of these. The dma code alternates between two buffers. It returns you one, as it start working on the other... It currently uses frameBuffer and frameBuffer2, but it could just as easily use sendImageBuf and half way through that buffer.

As for what do I use to do the actual DMA? I cheat. Inside the class I have:
Code:
enum {DMABUFFER_SIZE=1296};  // 640x480  so 640*2*2
	static DMAChannel _dmachannel;
	static DMASetting _dmasettings[2];
	static uint32_t _dmaBuffer1[DMABUFFER_SIZE];
	static uint32_t _dmaBuffer2[DMABUFFER_SIZE];
In the cpp file I have:

Code:
DMAChannel HM01B0::_dmachannel;
DMASetting HM01B0::_dmasettings[2];
uint32_t HM01B0::_dmaBuffer1[DMABUFFER_SIZE] __attribute__ ((used, aligned(32)));
uint32_t HM01B0::_dmaBuffer2[DMABUFFER_SIZE] __attribute__ ((used, aligned(32)));
 
@KurtE - just noticed I am getting a warning message:
Code:
D:\Users\Merli\Documents\Arduino\hm01b0_testv2\hm01b0_testv2.ino:360:85: warning: invalid conversion from 'void (*)(void*)' to 'bool (*)(void*)' [-fpermissive]
             hm01b0.startReadFrameDMA(&hm01b0_dma_callback, frameBuffer, frameBuffer2);            Serial.println("*** Return from startReadFrameDMA ***");
                                                                                     ^
In file included from D:\Users\Merli\Documents\Arduino\hm01b0_testv2\hm01b0_testv2.ino:25:0:
D:\Users\Merli\Documents\Arduino\libraries\TMM-HM01B0\src/HM01B0.h:134:7: note:   initializing argument 1 of 'bool HM01B0::startReadFrameDMA(bool (*)(void*), uint8_t*, uint8_t*)'
  bool startReadFrameDMA(bool (*callback)(void *frame_buffer)=nullptr, uint8_t *fb1=nullptr, uint8_t *fb2=nullptr);

Kurt - ignore this - got myself confused again.
 
@mjs513 Not a problem...

Question, as I start testing a couple of the ideas from yesterday for continuous DMA, should I work with testv2 or move on to testv3?

Also question to self (and maybe @Paul), currently my DMA is reading 32 bites in at a time, wonder if it can change to 16 bits as we are only looking at the lower word...
May try it. But first to try a couple of other quick DMA changes.
 
Morning all,

Not fully awake yet, nor had coffee,

We need to go through and maybe remove several of those buffers. Especially the uint16_t one that may not be used anymore as we don't convert from 8 bits to 16 bits...
Also should look at the sendImage stuff to see again to see if we can combine some of these. The dma code alternates between two buffers. It returns you one, as it start working on the other... It currently uses frameBuffer and frameBuffer2, but it could just as easily use sendImageBuf and half way through that buffer.

As for what do I use to do the actual DMA? I cheat. Inside the class I have:
Code:
enum {DMABUFFER_SIZE=1296};  // 640x480  so 640*2*2
	static DMAChannel _dmachannel;
	static DMASetting _dmasettings[2];
	static uint32_t _dmaBuffer1[DMABUFFER_SIZE];
	static uint32_t _dmaBuffer2[DMABUFFER_SIZE];
In the cpp file I have:

Code:
DMAChannel HM01B0::_dmachannel;
DMASetting HM01B0::_dmasettings[2];
uint32_t HM01B0::_dmaBuffer1[DMABUFFER_SIZE] __attribute__ ((used, aligned(32)));
uint32_t HM01B0::_dmaBuffer2[DMABUFFER_SIZE] __attribute__ ((used, aligned(32)));

Nice cheat. Anyway to the point. Just got rid of the last use of imageBuffer so deleting that one. As for the sendImageBuf that's really only used for when you are sending images to the Processing sketch.

To @Paul's question about cleaning things up. Think once things settle down what I would like to do is breakup our kitchen sink sketch to a series of sketches say (1) capture and save an image (2) watch video-like on tft and (3) Processing sketch. At least something along those lines.
 
@mjs513 Not a problem...

Question, as I start testing a couple of the ideas from yesterday for continuous DMA, should I work with testv2 or move on to testv3?

Also question to self (and maybe @Paul), currently my DMA is reading 32 bites in at a time, wonder if it can change to 16 bits as we are only looking at the lower word...
May try it. But first to try a couple of other quick DMA changes.

Work with v3. The only difference between v2 and v3 is the 'z' command for saving the last buffered image. Just tested it and its seems to be working with 's', 'D' and 'f' snapshots with hard faulting as @defragster mentioned.
 
@KurtE - just noticed I am getting a warning message:
Code:
D:\Users\Merli\Documents\Arduino\hm01b0_testv2\hm01b0_testv2.ino:360:85: warning: invalid conversion from 'void (*)(void*)' to 'bool (*)(void*)' [-fpermissive]
             hm01b0.startReadFrameDMA(&hm01b0_dma_callback, frameBuffer, frameBuffer2);            Serial.println("*** Return from startReadFrameDMA ***");
                                                                                     ^
In file included from D:\Users\Merli\Documents\Arduino\hm01b0_testv2\hm01b0_testv2.ino:25:0:
D:\Users\Merli\Documents\Arduino\libraries\TMM-HM01B0\src/HM01B0.h:134:7: note:   initializing argument 1 of 'bool HM01B0::startReadFrameDMA(bool (*)(void*), uint8_t*, uint8_t*)'
  bool startReadFrameDMA(bool (*callback)(void *frame_buffer)=nullptr, uint8_t *fb1=nullptr, uint8_t *fb2=nullptr);

Just an FYI- These days mostly avoid these issues of compiling for wrong board, as mostly work/build within sublime text and most of the time now using projects.
So for example in the test3 test directory I now have a file: hmb01b0_testv3.sublime-project
Code:
{
	"folders":
	[
		{
			"path": ".",
		},
		{
			"follow_symlinks": false,
			"path": "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\TMM-HM01B0",
		},
		{
			"path": "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\SparkFun_Himax_HM01B0_Camera"
		},
		{
			"follow_symlinks": false,
			"path": "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\ST7735_t3",
		},
		{
			"follow_symlinks": false,
			"path": "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\ILI9341_t3n",
		}
	],
}
Which you can easily do, except in my case where my setup is slightly strange. I put most of my github projects over on hard disk: d:\github\...
and create directory symbolic links into the Arduino libraries folder. By default sublime will dereference the links and walk it over to d: drive, but
when compile errors and like it will be against the arduino\libraries directory. But sublime has option to say don't follow... So I edit to do so...

I then use @frankB/@defragster setup for tset, and then do builds, I end up with windows that look like:
screenshot.jpg
Note: you can hit ESC or the like and the build results stuff area will go away and my sidebar is setup to disappear, and re-appear when mouse hovers over edge near it...

Now back from the diversion.
 
@KurtE
Once things settle down will have to go play with SublimeText and TSET again. Always something going on.
 
@mjs513 I am creating another branch working on DMA stuff (later for PR)...

Looks like made similar changes to what you did since then in DMA callback in sketch (last use of that buffer)... Missed when I setup the last/previous merge.

My current complete one looks like:
Code:
bool hm01b0_dma_callback(void *pfb) {
  //Serial.printf("Callback: %x\n", (uint32_t)pfb);
  if (tft.asyncUpdateActive()) return false; // don't use if we are already busy
  tft.setOrigin(-2, -2);
  tft.writeRect8BPP(0, 0, FRAME_WIDTH, FRAME_HEIGHT, (uint8_t*)pfb, mono_palette);
  tft.setOrigin(0, 0);
  tft.updateScreenAsync();

  last_dma_frame_buffer = (uint16_t*)pfb;
  return true;
}
I also removed that extra buffer.

On DMA stuff, I am trying changing the DMA stuff that when it completes a frame, it was setting up to get a VSYNC interrupt again... To simply instead setup for DMA operation to restart at that point. With these combined looks closer, to working, but the image walks itself across the screen...

If you wish to take a look it is in my DMA16 branch... I though I would try now converting the 32 bit DMAs to 16 to see if that works...
 
Send a pull request for continuous FlexIO DMA. I took the liberty of replacing Defragster's continuous "F" mode in hm01b0_testv3.ino.
 
@PaulStoffregen -
Just gave it a quick test spin using 'f' and continuous "F" mode. "f" works as well as before however "F" is having issues. The image seems to be loosing synch. Another run had it totally out of synch and looking like continuous DMA issues. Going to post a picture in a bit

Opps, sorry, I made some mistakes. Working on it now...
Guess I found it :)
 
@KurtE
Just merged your PR :)

EDIT: Just tested it and something strange going on with continuous mode. For the first bunch of frames the images are totally out of synch then all of sudden it settles down and works as you would expect it to - image good - everything in synch. This is what comes out on the SerMon:
Code:
startReadFrameDMA called buffers 20003668 20238400
20018844 400e9020:SA:401bc008 SO:0 AT:202 NB:4 SL:0 DA:20017380 DO:4 CI:510 DL:536971296 CS:12 BI:510
200187c0 200187e0:SA:401bc008 SO:0 AT:202 NB:4 SL:0 DA:20017380 DO:4 CI:510 DL:536971296 CS:12 BI:510
20018800 20018820:SA:401bc008 SO:0 AT:202 NB:4 SL:0 DA:20018860 DO:4 CI:510 DL:536971232 CS:12 BI:510
pclk pin: 8 config:1 control:13038
IOMUXC_GPR_GPR26-29:ffffffff ffffe00f ffffffff ffffffff
GPIO1: 100200c 100200c, GPIO6: 100200c 100200c
XBAR CTRL0:15 CTRL1:0

*** Return from startReadFrameDMA ***
*** stopReadFrameDMA ***
HM01B0::dmaInterrupt - Stop requested
20018844 400e9020:SA:401bc008 SO:0 AT:202 NB:4 SL:0 DA:20018860 DO:4 CI:510 DL:536971232 CS:92 BI:510
200187c0 200187e0:SA:401bc008 SO:0 AT:202 NB:4 SL:0 DA:20017380 DO:4 CI:510 DL:536971296 CS:1a BI:510
20018800 20018820:SA:401bc008 SO:0 AT:202 NB:4 SL:0 DA:20018860 DO:4 CI:510 DL:536971232 CS:12 BI:510

*** return from stopReadFrameDMA ***
 
Hi Mike, yep as I mentioned in the commit - it sort of walks through the screen a couple of times and then settles.

Will investigate. Right now playing with speeding up the VSYNC interrupt to see if that helps.

EDIT: Should have probably commented out the DEBUG_CAMERA define at start of .cpp file, which is what is printing that stuff.
 
Hi Mike, yep as I mentioned in the commit - it sort of walks through the screen a couple of times and then settles.

Will investigate. Right now playing with speeding up the VSYNC interrupt to see if that helps.

EDIT: Should have probably commented out the DEBUG_CAMERA define at start of .cpp file, which is what is printing that stuff.

My turn for Oops - missed that in the PR was looking at the changes more :) I don't mind the debug stuff.
 
@PaulStoffregen -
Just gave it a quick test spin using 'f' and continuous "F" mode. "f" works as well as before however "F" is having issues. The image seems to be loosing synch. Another run had it totally out of synch and looking like continuous DMA issues. Going to post a picture in a bit

Yup, sent a pull request just now. I'm not sure it's 100% working yet. I'm seeing a lot more VSYNC interrupts than screen refreshes. I added a some code to print the actual refresh rate.
 
@Paul - There appears to be an issue in the imxrt.h file... Not specific to MicroMod.

Not sure best way to fix as associated with the GPIO structures...
That is we have:
Code:
// 12.5.1: page 961
typedef struct {
        volatile uint32_t DR;                  // 00
        volatile uint32_t GDIR;                // 04
        volatile uint32_t PSR;                 // 08
        volatile uint32_t ICR1;                // 0C
        volatile uint32_t ICR2;                // 10
        volatile uint32_t IMR;                 // 14[COLOR="#FF0000"]
        volatile uint32_t ICR;                 // 18[/COLOR]
        volatile uint32_t EDGE_SEL;            // 1C
        uint32_t          UNUSED[25];          // 20 - 83
        volatile uint32_t DR_SET;              // 84
        volatile uint32_t DR_CLEAR;            // 88
        volatile uint32_t DR_TOGGLE;           // 8C

} IMXRT_GPIO_t;

In the code where I was going to emulate attachInterrupt with code to use GPIO4 for it, so I did:
Code:
    GPIO4_ISR = _vsyncMask; // make sure it is clear
Problem is: that is defined as:
Code:
#define GPIO4_ISR			(IMXRT_GPIO4.ISR)
And says ISR is not a member of that class...
For some reason it is called ICR in the structure, although the RM shows the register name as ISR.
Could fix 2 ways:
change those defines to ICR (or) could change structure to be ISR?

I am leaning to change structure. Did not actually see anywhere that references it.
 
@mjs513 - Paul has a PR pending on your git.

... here a short time - github desktop not showing me changes ... another remove/and fork ... arrgh

Still seeing this ugly (hard coded static) save_image_SD() work-around for the 'Data bus' HardFault :: DMAMEM unsigned char img[3 * 320*240];

DMA "D" and FlexIO 'f' working w/ili9341

'd' has a cute image centering pass then goes stable as noted.

'F' seems to toggle a sync and unsync version image in turn - ends up hung in some fashion after stopping - assume that fix in Paul's PR.

I see a CORES change for imxrt.h - if I take that I lose the Print HardFaults to manually redo -
@Paul is that PR_535 going to get included in TD 1.54? I made a change to get USER SKETCH call - that wasn't moved in - it would allow Faulting sketch to record added 'state' info for display on restart - like a dump of registers or other.

... offline an hour or so ...
 
Yup, sent a pull request just now. I'm not sure it's 100% working yet. I'm seeing a lot more VSYNC interrupts than screen refreshes. I added a some code to print the actual refresh rate.

PR just merged. Sorry for the delay - had to run out and do a few errands.
 
Back
Top