MicroMod Beta Testing

Yeah, 4 bit mode appears to be a HM01B0 specific feature.

The breakout board applies 3.3V power. Don't plug any non-HM01B0 cameras in if they need 1.8V power!
 
It will be interesting, as I so far like the OV7670 cameras better than the ... And so far I don't see anything about them supporting a 4 bit mode. I am probably missing something.

I have also sort of been off doing some other stuff today.

I think the OV camera's work in 4-bit mode either. When I was saying common denominator I was talking about between MM, T4.1 and T4.0. I wasn't suggesting between cameras. Personally I like the OV cameras better as well.....


EDIT: Sorry Paul - didn't see your post.
 
...
If you want to get access to the 13 test points on the bottom of the MicroMod PCB
...

Ah Test points - indeed they are clearly wired that way. That solves some wonder about those large 'vias' and those 'T' pins. Nothing to see here.

Didn't connect display yet - turned on SDCARD - is has this func call to remove:
Code:
T:\tCode\libraries\HM01B0\examples\HM01B0_example1\HM01B0_example1.ino:296:15: error: 'calAE' was not declared in this scope
         calAE();

And image doesn't find right filename here and doesn't try to create the file? That seems familiar to latest ML.mm test?

Power Off/On works. Didn't wire vBat yet.

Running NewPinTest : on powerup I see Pullups on 18/19.
Side pins 0-23 work going high ( 18/19 already hi ) -
On each end RTS / CTS no connect - known not brought out.

Up the other side Good #24 to #37 and #40 to #45

PINS 38 and 39 show swapped by Teensy pin number : I.e. DAT2 and DAT3

Reading SD card pins from end L>R:
#34
#35
> GND
#36
> 3.3V
#37
#38 { DAT3 on T_4.1 card #47 }
#39 { DAT2 on T_4.1 card #46 }

-> by label from T_4.1 DAT3 and DAT2 names match where they are swapped above on the edge ?

OPPS < EDIT >: - posted before noting/confirming
Referring to @mjs513 ATP Pin Card :: Pin #39 is shown as ( CS1/SDIO_DAT3 )
- the card does not show ATP bringing pin #38 out and does not have SD socket

Can that be double checked, i.e. the pins activated in NewPinTest and showing swapped for #38 and #39?

<edit2> : can't compare to ML.mm SD as it uses SPI pins not SDIO.
 
Last edited:
Ok trying to figure out how to just read 4-bits instead of 8 and didn't want to admit that I have very little clue what this is doing:
Code:
uint32_t in =  (GPIO7_PSR >> 4); // read all bits in parallel
but if you indulge me a bit I am going to try and walk through this in my mind:
1. Our data pins are: 40, 41, 42, 43, 44, 45, 6 and 9
2. data pins are on: 2:04 ,2:05, 2:06, 2:07, 2:08, 2:09, 2.10 and 2.11 respectfully. so 2:0-2:3 are not involved so is this the reason for the shift >>4?
3. and that pinset is on GPIO7 according core_pins.h
and
4. According to the RM GPIO_PSR contains the data.

Is this pretty much it.

The other method I saw posted while not pertaining to this application is:
Code:
(GPIO7_DR & CORE_PIN6_BITMASK)  >> CORE_PIN6_BIT         | 
            (((GPIO7_DR & CORE_PIN7_BITMASK)  >> CORE_PIN7_BIT) << 1)  |
            (((GPIO7_DR & CORE_PIN8_BITMASK)  >> CORE_PIN8_BIT) << 2)  |
            (((GPIO7_DR & CORE_PIN9_BITMASK)  >> CORE_PIN9_BIT) << 3)  |
            (((GPIO7_DR & CORE_PIN10_BITMASK) >> CORE_PIN10_BIT) << 4) |
            (((GPIO7_DR & CORE_PIN11_BITMASK) >> CORE_PIN11_BIT) << 5) |
            (((GPIO7_DR & CORE_PIN12_BITMASK) >> CORE_PIN12_BIT) << 6) |
            (((GPIO7_DR & CORE_PIN13_BITMASK) >> CORE_PIN13_BIT) << 7);

Next step for 8bit we have:
Code:
	for (uint8_t pin : {G0, G1, G2, G3, G4, G5, G6, G7})
	{
		pinMode(pin, INPUT_PULLUP);
	}
for 4 bit we would have
Code:
	for (uint8_t pin : {G0, G1, G2, G3})
	{
		pinMode(pin, INPUT_PULLUP);
	}
since the data comes out on the lower 4bits from the camera (D0-D3).
So GPIO7_PSR >> 4 should still work for 4 bit?????? or am I missing he obvious?

So now how to combine the values?

EDIT: Ok time for zzzz's
 
UPDATE on SDIO SD CARD on PJRC MMod Breakout:

Captured BMP Image from Camera Does make it to the SD card using ::
Code:
  if (!SD.begin(BUILTIN_SDCARD)) {
//  if (!SD.begin(10)) {

But according to NewPinTest reading ( in p#553 ) - the silkscreen on edge pins #38/39 is swapped.

And the current sketch :: HM01B0_example1.ino on that MMod Breakout can read 8 bit camera { was set for GPIO_8BIT } and save to SDIO SD card - even with no display yet wired!
 
Yeah didn’t mention it but you can save to sd, send to the processing sketch or use the arducam app to see the image without the display in all modes selected :) gpio, small or flex
 
Yeah didn’t mention it but you can save to sd, send to the processing sketch or use the arducam app to see the image without the display in all modes selected :) gpio, small or flex

Cool - I hadn't tested image xfer lately - downloaded the ArduCam app - but not yet tried it.

This was just a pin test of the breakout and seeing why SD (10) failed ... because it is BUILTIN_SDCARD! Time for yet another IFDEF :)
 
Ok trying to figure out how to just read 4-bits instead of 8 and didn't want to admit that I have very little clue what this is doing:
Code:
uint32_t in =  (GPIO7_PSR >> 4); // read all bits in parallel

It is just copying the current bits fromGPIO7_PSR (input register) to the variable in and shifting everything 4 bits to the right to account for the fact that the MM pins sit on bit 4-11 of GPIO7.
Screenshot 2021-04-22 071922.jpg

When you assign to a uint32_t you need to be aware that bits 8-31 will contain values depending on the state of the corresponding (shifted) pins. So, if necessary, either assign it to an uint8_t or mask them with "... &= 0xFF".


The other method I saw posted while not pertaining to this application is:
Code:
(GPIO7_DR & CORE_PIN6_BITMASK)  >> CORE_PIN6_BIT         | 
            (((GPIO7_DR & CORE_PIN7_BITMASK)  >> CORE_PIN7_BIT) << 1)  |
            (((GPIO7_DR & CORE_PIN8_BITMASK)  >> CORE_PIN8_BIT) << 2)  |
            (((GPIO7_DR & CORE_PIN9_BITMASK)  >> CORE_PIN9_BIT) << 3)  |
            (((GPIO7_DR & CORE_PIN10_BITMASK) >> CORE_PIN10_BIT) << 4) |
            (((GPIO7_DR & CORE_PIN11_BITMASK) >> CORE_PIN11_BIT) << 5) |
            (((GPIO7_DR & CORE_PIN12_BITMASK) >> CORE_PIN12_BIT) << 6) |
            (((GPIO7_DR & CORE_PIN13_BITMASK) >> CORE_PIN13_BIT) << 7);
Something like this is necessary if the pins you want to access are on non-consecutive positions in the GPIO register. Here I don't see a necessity to do this. After all, the hole point of the 8bit port on the MM is to enable parallel read/write access to it.

Next step for 8bit we have:
Code:
	for (uint8_t pin : {G0, G1, G2, G3, G4, G5, G6, G7})
	{
		pinMode(pin, INPUT_PULLUP);
	}
for 4 bit we would have
Code:
	for (uint8_t pin : {G0, G1, G2, G3})
	{
		pinMode(pin, INPUT_PULLUP);
	}
since the data comes out on the lower 4bits from the camera (D0-D3).

Sure, the code above is just a shorthand for doing a
Code:
pinMode(G0, INPUT_PULLUP);
pinMode(G1, INPUT_PULLUP);
pinMode(G2, INPUT_PULLUP);
pinMode(G3, INPUT_PULLUP);
pinMode(G4, INPUT_PULLUP);
pinMode(G5, INPUT_PULLUP);
pinMode(G6, INPUT_PULLUP);
pinMode(G7, INPUT_PULLUP);

So GPIO7_PSR >> 4 should still work for 4 bit?????? or am I missing he obvious?
sure. Actually you don't have to change anything, just use the lower 4 bits of the variable 'in'. You might consider masking to get rid of possible values from other pins:
Code:
in &= 0x0F
 
RE: Pin #9 for D/C : Looks like Pin 9 to DC feeds through that display header on its way to the Camera header. Don't cut or it will take a second wire to get 9 over to the camera's tiny gauge pin.

>> DID PR mjs513/TMM-HB01B0-Camera/pull/17

Wrote the note below - decided to move wired ST7789 to PJRC.mm.b - IT WORKS! { after getting build with current KurtE_master_st7735_t3 }
> f works, and "F" ran a whole series shifting over one pixel per update - it seemed - so 240 updates later it got ZEROED and stayed there!
- > Note the "F" wiggling fingers tearing is present - even slow moving shows some scan areas are not updated in sync with the others.
>> VID has shifting out of sync update: Shifting across the short dimension - and at same time parts of scan lines are shifting across the long edge and it doesn't ever get to full sync.

<edit>: before solder did a 4" ribbon wire set to ILI9341 and hand wired the DC to #4 - this display works as well - but the "F" does not have the finger wiggle issue on the 9341, but VID 'sync' still broken.

Added #ifdef to move pins for PJRC.mm.B

trying dual Serial to ArduCam these build errors - fixed? changed name on cont_mode ??:
Code:
T:\tCode\libraries\HM01B0\examples\HM01B0_example1\[B]HM01B0_example1.ino:267:15[/B]: error: 'calAE' was not declared in this scope
         calAE();
               ^
T:\tCode\libraries\HM01B0\examples\HM01B0_example1\[B]HM01B0_example1.ino:281:9[/B]: error: 'g_continuous_mode' was not declared in this scope
         g_continuous_mode = false;
Note: another "calAE()" was noted before.

Not seeing that ArduCam.exe give an image - just a long slow print of data spew in the text window? Maybe I need to restart as it had to pull in some .NET to run.

PDE getting and showing something - but not an image at all.

I'll be in better shape when I dare to unscrew the rest of the PJRC breakout and solder headers and cut the pin 9 trace. I managed to push the camera cable in and latch without unscrewing.

SD card under display going to be tough to manage. The newest ST7789 with wires to a header easy enough - might just do the same with piece of ribbon to the ILI9341

Using wires to display header allows change of DC as needed (cam shared p#9) and access to SD card as well.
 
Last edited:
@luni
Thanks for the detailed explanation - learning something new everyday - you know one of these days something like this should be written up and put on the wiki (I know have checked lately) since I think I have seen a few posts asking about this stuff before. EDIT: forgot I hate dealing with masks :) But yep have to do the mask

@defragster
Going to retest when I get the breakout board with the ILI9341.

I did test 'f' and "F" in the 3 modes. Only one I seemed to have an issue with was DMA with "F" and "VID" as you mentioned. Didn't notice any tearing with the with the other modes.

calAE should work for snapshots in all modes now - unless I forgot to push that change.

As for Arducam.exe - think you are using the wrong one as I mentioned before. Download this version: https://github.com/ArduCAM/Arduino/tree/master/ArduCAM/examples/host_app/ArduCAM_Host_V2.0_Windows
 
Last edited:
@defragster
I merged your pull request then noticed that you deleted some stuff that is needed for GPIO continuous mode. Have to go over it in more detail after I have my coffee.

EDIT: this is the latest card version I have:
Picture1.jpg

which should correspond to the MM Connector:
Capture.PNG
 
Last edited:
Morning all (Still need coffee)

Will sink and Play... I am not sure if it is a good next approach, but I might see how well I can adapt the FlexIO code to maybe use some of the stuff in my FlexIO library. i.e. see how well it adapts.

Then maybe if for example 4 bits mode works, then I have all of the code in place to allow you to choose different ports/pins and it will take care of the configuration data...

As for GPIO and reading in the 4 or 8 bits, with the MMOD board as you mentioned we are doing: uint32_t in = (GPIO7_PSR >> 4); // read all bits in parallel
With some of the GPIO code again as you showed the bits are not contiguous, so the code on T4 was doing something like:
Code:
      uint16_t b = buffer[i] >> 18;
      b = (b & 0x3) | ((b & 0x3f0) >> 2);

I thought I would mention that there is a 3rd setup, that on T4.1, if you are using the CSI pins:
Code:
1.22	17/A3	CSI_VSYNC
1.23	16/A2	CSI_HSYNC
1.24	22/A8	CSI_D9
1.25	23/A9	CSI_D8
1.26	20/A6	CSI_D7
1.27	21/A7	CSI_D6
1.28	38/A14	CSI_D5
1.29	39/A5	CSI_D4
1.30	26/A12	CSI_D3
1.31	27/A13	CSI_D2
You will notice that the 8 GPIO pins are in consecutive order at the top of register and in reverse order
So in this case I use: uint32_t in = __RBIT(GPIO6_PSR); // read all bits in parallel
Which reads in all of the bits and reverses them bit wise... so the 8 bits end up at the start of the uint32_t in the correct order...
 
Morning all (Still need coffee)

Will sink and Play... I am not sure if it is a good next approach, but I might see how well I can adapt the FlexIO code to maybe use some of the stuff in my FlexIO library. i.e. see how well it adapts.

Then maybe if for example 4 bits mode works, then I have all of the code in place to allow you to choose different ports/pins and it will take care of the configuration data...

As for GPIO and reading in the 4 or 8 bits, with the MMOD board as you mentioned we are doing: uint32_t in = (GPIO7_PSR >> 4); // read all bits in parallel
With some of the GPIO code again as you showed the bits are not contiguous, so the code on T4 was doing something like:
Code:
      uint16_t b = buffer[i] >> 18;
      b = (b & 0x3) | ((b & 0x3f0) >> 2);

I thought I would mention that there is a 3rd setup, that on T4.1, if you are using the CSI pins:
Code:
1.22	17/A3	CSI_VSYNC
1.23	16/A2	CSI_HSYNC
1.24	22/A8	CSI_D9
1.25	23/A9	CSI_D8
1.26	20/A6	CSI_D7
1.27	21/A7	CSI_D6
1.28	38/A14	CSI_D5
1.29	39/A5	CSI_D4
1.30	26/A12	CSI_D3
1.31	27/A13	CSI_D2
You will notice that the 8 GPIO pins are in consecutive order at the top of register and in reverse order
So in this case I use: uint32_t in = __RBIT(GPIO6_PSR); // read all bits in parallel
Which reads in all of the bits and reverses them bit wise... so the 8 bits end up at the start of the uint32_t in the correct order...

Morning @KurtE - well. I can confirm that 4-bit mode works. Just kludged up my local copy to try 4-bit using GPIO only. Only register that needs to changed it seems is 0x3059 (BIT control) so bit 6 is set to 1 and bit 5 is set to 0. 0x3060 (OSC_DIV) sets the bit order (MSB or LSB) in bit 4 buts its already set up for MSB first.

So thats what _RBIT means in the code :) Good to know.

Let me do some clean up and will push the change for 4-bit for GPIO as well as incorporate @defragster changes
 
@KurtE - @defragster
Just pushed a bunch of changes to the API-rework branch to test 4-bit mode in GPIO mode only. Pretty sure its working.

@defragster - incorporated some your changes - example 'F' now works in GPIO mode so left that code in at least for now. Also, using the generic functions for "F" since it covers both DMA and FLEXIO continuous modes. GPIO is done slightly differently with only readframe.

Somethings I don't like is the way I currently have the pins setup. Best way to change ????

EDIT: Now for more coffee!!!!!

Thanks @luni - @KurtE for the bit manipulation explanation :)

Forgot to check calAE - next up :)
 
@mjs513 (and others) - I know I should probably RTFM and/or code, but what does 4 bit mode mean?
Does it mean that it still reads in 8 bit monochrome, i.e 256 shade, but takes two GPIOs to receive the data?

Or does it mean that there are only 16 shades? and in which case should we (and maybe already do), use a different mapping table? and/or should the data be packed 2 per byte and use: writeRect4BPP instead of writeRect8BPP?

Again I know I should RTFM(C) ;)
 
Morning Kurt
4bit mode for me anyway means that it just takes 2 reads to get the 8bits for the each pixel. First transfer gets you the upper 4bits of the pixel and the second transfer gets you the lower 4bits of the pixel. So you still have the full 8bits just need to do 2 reads :)

Been reading a lot again and its giving me a head ache!

Just to keep things straight I added a new function readFrame4BitGPIO. Its basically the old readFrameGPIO with the following changes:
Code:
  uint8_t in0;
  
  //Change for Monodchrome only Sparkfun HB01b0
  #if defined(SensorMonochrome) 
	_grayscale = false;
	bytesPerRow = _width * 2;
  #else
	_grayscale = (pixformat == PIXFORMAT_GRAYSCALE);
	bytesPerRow = _width * 2 * 2;
  #endif
.......
      //uint32_t in = ((_frame_buffer_pointer)? GPIO1_DR : GPIO6_DR) >> 18; // read all bits in parallel
      uint8_t in =  (GPIO7_PSR >> 4); // read all bits in parallel
	  //uint32_t in = mmBus; 
	  in &= 0x0F;
	  
	  if((j + 1) % 2) {
		  in = (in0 << 4) | (in);
		  if (!(j & 1) || !_grayscale) {
			*b++ = in;
		  }
	  } else {
		  in0 = in;
	  }
	  
      while (((*_pclkPort & _pclkMask) != 0) && ((*_hrefPort & _hrefMask) != 0)) ; // wait for LOW bail if _href is lost
Feel free to edit.

EDIT: know its not really bytesperrow :)
 
Looks like the same stuff... Gets the job done...

Will try to play some today. I did verify it does read on the Machine Learning on ST7789 :D
 
Looks like the same stuff... Gets the job done...

Will try to play some today. I did verify it does read on the Machine Learning on ST7789 :D

Cool - glad its working.

Now trying to figure this one out:
Code:
FLEXIO_SHIFTCFG_PWIDTH(7);
think it just needs to get changed to
Code:
FLEXIO_SHIFTCFG_PWIDTH(3);
and of course use only 4 pins.
 
That should do it!... I think....

Except will be interesting as it will only shift 4 bits into shift register, so question will be do we get an output from shift register when the 4 bits come in or when it fully fills the shift register?
 
Well that change alone seems to work but the data transfer has to be modified since its only set up for Bytes. Not sure how to do that one :)

EDIT: Will push what I have up that I did with the Flexio and maybe you see something since I am just getting into it and trying to read the RM - argh - my head hurts - seem to say that every time I read the RM's.

EDIT: just pushed :)
 
Just got the new breakout board and gave FlexIO a try and in the image below you can see what the problem is - reading the 4bits but skipping every other one so shading will be off:
IMG-0360.png
Not sure how to fix this one.
 
@mjs513 - yes wrong arduCam here - left it a day or so and on return I pulled the other one that fails, thanks for re-link. Using that but not seeing anything yet? Settings?

> Not sure why anything useful left in my PR - glad you caught it. Except I may have deleted a Used item before I had Dual Serial on as Unused?

Updated and the "calAE();" is not found in "HM01B0_example1.ino" ? Just pulled it in from KitchenSink ???

Using the PJRC.mm.B board with Himax on the 8 bit port, w/ST7789.

'f' works and '_hmConfig 0' works great on "F" - but in '_hmConfig 2' does the full 240 cycles before it gets into 'registration' and has the 'finger wiggle issue' on right edge of ST7789

I see '_hmConfig 3' 4 bit GPIO working! - no Finger Wiggle on "F" that works!
 
@defragster
Did catch and made the change to test for MM_ML for SD.begin. Left the ML stuff in.

'_hmConfig 0' - GPIO8bit: 'f' works fine. Been running 'F' quite a while no with no finger tearing noticable.
'_hmConfig 2' - HM01B0_TEENSY_MICROMOD_DMA_8BIT: 'f' works great. 'F' and 'V' not working - think thats something @KurtE has to check out I think. Saw it on the 7789 as well
'_hmConfig 2' - change frameRate to 15fps and 'F' works great. Picture nice and steady.
'_hmConfig 1' -both work fine as far as I can see.
'_hmConfig 3' 4 bit GPIO: as you said 'f' is working - funny I can see my fingers wiggling using 'F'. Oh one note. I hooked up display directly to header and am using pin 9 since in 4bit mode pin 9 isn't used anymore for data :)

Using that but not seeing anything yet? Settings?
Capture.PNG
Make sure you have "Set to BMP" selected before you hit capture. And size set to 320x240 Don't need the IP address.
 
Just got the new breakout board and gave FlexIO a try and in the image below you can see what the problem is - reading the 4bits but skipping every other one so shading will be off:
View attachment 24528
Not sure how to fix this one.

I will take a look, but one hair brain idea is to leave FLEXIO_SHIFTCFG_PWIDTH(7);
But not configure those pins as FlexIO. Long term not good, as maybe I want to use them for some other FlexIO thing...
 
Back
Top