Problem trying to read OV7670 camera under IRQ Teensy 4.0

Status
Not open for further replies.
Hi Cyrille,

no I don't know the OV7670.

What I know is that you are generating the clock for the OV7670 using the PWM feature of the Teensy 4, and you are driving it to its limits, have a look at the tables at https://www.pjrc.com/teensy/td_pulse.html. The F_BUS speed driving the PWM tick runs at a quarter of the F_CPU speed so at 150MHz, and if you request a 12MHz square wave by analogWriteFrequency(PinCamXclk,12000000); analogWrite(PinCamXclk,127) frankly I don't know how exact the square wave will be.

Within the limits of my 60MHz oscilloscope, it seems you get pretty good square waves when you request an analogWriteFrequency() which divides into 150MHz an even number of times:

150/6 = 25.00MHZ
160/8 = 18.75MHz
150/10 = 15.000 MHz
150/12 = 12.50MHZ
150/14 = 10.71MHz
150/16 = 9.375MHz

I'll probably start with one of the lower frequencies for XCLK until I get around to switching from a breadboard and jumper wires to a carefully solved breadboard with shorter wires.
 
Hello,

I have posted my project code on gitHub: https://github.com/Cyrille-de-Brebisson/arduViseur

Of course, the code does much more than just handle the camera! but the camera code is there...

It does require the your iliteck screen library. But I had to change the SPI speed in said library to 15Mhz for things to work for me.

The pin connection is in the main .ino file.

At this point in time, the camera is set to B&W because this is what I need.

Cyrille
 
Thanks, I thought I would try to build your stuff, and maybe hook up my wiring the same, to start just to see if I get the camera to work and then go from there...

What I am curious about is it looks like you are doing your own bitbang SPI implementation for the touch screen. Where you are using additional pins for
Code:
#define TouchClk    6  // B0_10
#define TouchCS     7  // B1_01
#define TouchDOUT   8  // B1_00
#define TouchDIN    9  // B0_11S
Did you run into issues just using straight SPI with just one additional pin for CS (maybe two ) for IRQ and using the XPT2046_touchscreen library that ships with Teensyduino?

Again it is your project and ... But just sort of wondering.
 
Also since I am playing with a T4.1 instead of a T4... Will probably change what IO pins are read for camera...

That is if you look at the Port\:pin to hardware pin:
Code:
6:02, 01
6:03, 00
6:12, 24
6:13, 25
6:16, 19
6:17, 18
6:18, 14
6:19, 15
6:20, 40
6:21, 41
6:22, 17
6:23, 16
6:24, 22
6:25, 23
6:26, 20
6:27, 21
6:28, 38
6:29, 39
6:30, 26
6:31, 27
7:00, 10
7:01, 12
7:02, 11
7:03, 13
7:10, 06
7:11, 09
7:12, 32
7:16, 08
7:17, 07
7:18, 36
7:19, 37
7:28, 35
7:29, 34
8:18, 28
8:22, 31
8:23, 30
9:04, 02
9:05, 03
9:06, 04
9:07, 33
9:08, 05
9:31, 29

8:15, 42
8:14, 43
8:13, 44
8:12, 45
8:17, 46
8:16, 47
9:24, 48
9:27, 49
9:28, 50
9:22, 51
9:26, 52
9:25, 53
9:29, 54
I left it split at underpins as will probably only normal pins... But easy to get contiguous 8 pins...

Edit: May punt for now on touch... although may simply convert to the normal library... Of if there is a problem with it on the same SPI.
Could also use my SPI implementation using FlexIO pins.
 
Hello,

Yes, I was having some issues with the Touch SPI.

At the beginning, I was working with the LCD on async, continuous auto update.
This means that I would have needed to integrate/build in the touch SPI read within the LCD library so that after each LCD out, it would do a touch read.
This would IMHO be the best solution, but I did not manage to do it since I have never dug deeply into your code...

Also, without any breadboard or anything like this, I am working with wires... and they have only 2 connections. Sharing the pins would mean having a wire with 3 connectors. Which I did not have... Hence the solution I used.
Since I only do reading 20 times per second or so, bit banging the touch SPI was not a big deal.

I am also doing my own screen drawing (so that my code can also work on windows, which is my "development" platform for all non HW releated things).
I wish I could extract your SPI to screen code and just use this, but with the number of #defines I am not clear enough on what is, or is not used to do so.
I also started looking at what it would take to place the screen in a non cacheable region to avoid some of the cache issues that you have to handle in your code. but I don't have enough info to make this work.

Cyrille
 
Using the IRQ notify of touch with the XPT2046_touchscreen generally worked well on T_3.x. Just ignore touch until it is reported. Though on T_4.x I did see some signs of it acting as if a touch was seen after touch was stopped that wasn't looked at very hard or otherwise reported yet.

From what I did see with the SPI LED on that pin it seemed like the IRQ was hitting again on T_4.0 - which causes a read - which triggered an IRQ ... The IRQ is disabled during read I/O - but perhaps a race where enabling IRQ after read catches the touch hardware then reporting another IRQ starting the chain over. Seems I tried to edit the code to stop that and it didn't seems to be fixed before I moved on. This is seen as the pin 13 LED dribbling to a stop after touch stops.
 
Sorry I got diverted... What else is new ;)

Again I wondered about why you did the XPT2046 bitbang... Then looked at XPT2046 code and it is/was hard coded to only work with SPI.

So I updated it to allow the begin method to pass in a different SPI object:
https://github.com/PaulStoffregen/XPT2046_Touchscreen/pull/33


But I also wondered about doing it with my FlexIO library SPI implementation. Again only T4.x...

So I added the ability in that above PR to include my library; https://github.com/KurtE/FlexIO_t4

And it was having problems. Turns out my transfer16 was transfering bytes in wrong order, so fixed it internally to just do two transfers. It now works..
I tried on SPI1 pins on T4.1. There is a set that works either as SPI1 or as FlexIO pins...

Hopefully I can now reconfigure back to use your pins which are also flexIO pin.

Hopefully now will get back to camera ;)
 
Now looking at signals from Camera.

Got out my older Logic Analyzer (Logic16) to see all of the signals, but does not run as fast as my newer ones....

But here is a capture showing the sketch running:
screenshot.jpg
In this the top 8 lines are the 8 data pins, followed by 4 pins (2-5)
Code:
#define PinCamVsync 2  // EMC_04
#define PinCamHref  3  // EMC_05
#define PinCamPpclk 4  // EMC_06
#define PinCamXclk  5  // EMC_08
Last two are the Wire pins, which only appeared to do something at startup...
So looks like Channel 8(PinCamVsync ) - Looks like it does a pulse at the start and end of an image.
Channel 9 appears to be high for each scan line.
Still need to see difference between 10-11 as PPCLK appears to run at about 2mhz and XClk appars to run at 8mhz...
More details shown in closer up:
screenshot2.jpg

Edit and closer up:
screenshot3.jpg

Now to walk through current code. And maybe see if one were to try to do this DMA... Note: I personally will be setting this up for T4.1 as more IO pins on the same IO port...
Question will be how many pins to actually capture. Should it run continuously? Or triggered, by something like VSync? Or maybe by H...?

Could be fun...
 
Not sure if I should start a new thread or continue here... But assuming I actually follow through and it works, it might be interesting. Should probably try the camera interface, but first I am curious if I can remove most of your interrupt handling and have it taken over by DMA... Not sure yet if it makes sense to do the DMA on a one line basis or if it should continue running...

But thinking start off with doing the one line at a time...

@Paul and/or ... who has played more with DMA and GPIO and XBar and all of the other glue, feel free to chime in on suggestions.

Sort of the steps I think I need to do to get it to work include:

Data pins: Lets assume they are on GPIO6(GPIO1) - Could be the pins you are currently using or on T4.1, could use a contiguous 8 GPIO pins. Note: me excel document I added some duplicate pages that have the pins in GPIO order:
Code:
 1	AD_B0_02	1.02	Serial1(6) TX		SPI1(3) MISO	PWM1_X0	2_TX		IO-16			
 0	AD_B0_03	1.03	Serial1(6) RX		SPI1(3) CS0	PWM1_X1	2_RX		IO-17			
24/A10	AD_B0_12	1.12	Serial6(1) TX	Wire2(4) SCL		PWM1_X2					A1:1  	
25/A11	AD_B0_13	1.13	Serial6(1) RX	Wire2(4) SDA		PWM1_X3	GPT1_CLK				A1:2	
[COLOR="#FF0000"]19/A5	AD_B1_00	1.16	Serial3(2) CTS	Wire(1) SCL		QT3_0				3:0	A1:5, A2:5	
18/A4	AD_B1_01	1.17	Serial3(2) RTS	Wire(1) SDA		QT3_1				3:1	A1:6, A2:6	
14/A0	AD_B1_02	1.18	Serial3(2) TX			QT3_2		SPDIF_OUT		3:2	A1:7, A2:7	
15/A1	AD_B1_03	1.19	Serial3(2) RX			QT3_3		SPDIF_IN		3:3	A1:8, A2:8	
40/A16	AD_B1_04 	1.20								3:4	A1:9,A2:9	USDHC2_DATA0
41/A17	AD_B1_05 	1.21				GPT2_1				3:5	A1:10,A2:10	USDHC2_DATA1
17/A3	AD_B1_06	1.22	Serial4(3) TX	Wire1(3) SDA				SPDIF_LOCK		3:6	A1:11, A2:11	USDHC2_DATA2
16/A2	AD_B1_07	1.23	Serial4(3) RX	Wire1(3) SCL				SPDIF_EXTCLK		3:7	A1:12, A2:12	USDHC2_DATA3[/COLOR]
22/A8	AD_B1_08	1.24				PWM4_A0	1_TX			3:8	A1:13, A2:13	USDHC2_CMD
23/A9	AD_B1_09	1.25				PWM4_A1	1_RX	1:MCLK		3:9	A1:14, A2:14	USDHC2_CLK
20/A6	AD_B1_10	1.26	Serial5(8) TX					1:RX_SYNC		3:10	A1:15, A2:15	
21/A7	AD_B1_11	1.27	Serial5(8) RX					1:RX_BCLK		3:11	A1:0, A2:0	
38/A14	AD_B1_12 	1.28			SPI1(3) CS0 			1:rx_data 		3:12	A2:1	
39/A5	AD_B1_13 	1.29			SPI1(3) MISO			1:tx_data 		3:13	A2:2	
26/A12	AD_B1_14	1.30			SPI1(3) MOSI			1:TX_BCLK		3:14	A2:3  	
27/A13	AD_B1_15	1.31			SPI1(3) SCK			1:TX_SYNC		3:15	A2:4
Example the ones in RED...
Need to switch these IO pins back to GPIO1 (Probably the correct bits in: IOMUXC_GPR_GPR26 = 0xFFFFFFFF;)

Need to setup DMA operation probably similar to what is in the OctoWS2811
Code:
	// configure DMA channels
	dma1.begin();
	dma1.TCD->SADDR = bitmask;
	dma1.TCD->SOFF = 8;
	dma1.TCD->ATTR = DMA_TCD_ATTR_SSIZE(3) | DMA_TCD_ATTR_SMOD(4) | DMA_TCD_ATTR_DSIZE(2);
	dma1.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
		DMA_TCD_NBYTES_MLOFFYES_MLOFF(-65536) |
		DMA_TCD_NBYTES_MLOFFYES_NBYTES(16);
	dma1.TCD->SLAST = 0;
	dma1.TCD->DADDR = &GPIO1_DR_SET;
	dma1.TCD->DOFF = 16384;
	dma1.TCD->CITER_ELINKNO = numbytes * 8;
	dma1.TCD->DLASTSGA = -65536;
	dma1.TCD->BITER_ELINKNO = numbytes * 8;
	dma1.TCD->CSR = DMA_TCD_CSR_DREQ;
	dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_0);
But the above is to do a write operation, I need it instead to do the READ operation, so SADDR and DADDR will be different and likewise the GPIO register will be the IO state.

Now like the above I think I also need to setup the XBAR to DMA operation and it will be the SOURCE... Not sure if I should use the same one here... Not sure if we would be able to run both the camera and the OCTOWS2811 on same T4.x?

Now for what should the Source be to the XBAR... The Octo is using a Timer. But in this case I think the Timer that was setup for PWM is not the right signal, should be the HREF signal which on every 4th of the clocks...

So then the question is how to feed this on to XBAR? Right now using pin 3, which could work. If you look that pins data we have:
Code:
 3	EMC_05	4.05				PWM4_B2		2:TX_SYNC	[COLOR="#FF0000"]IO-07[/COLOR]	1:5
So how to feed it in. I believe I can convert that pin to be in XBar Mode: Mode 3 in this case.

And then our input to the XBAR would probably be: XBARA1_IN_IOMUX_XBAR_INOUT07

Would also have to configure this one to be in INPUT mode... Maybe might have to setup the IOMUXC_... to make sure it routes the input from the right pad...

I think that might be it...

Hopefully this is as clear as mud! What could go wrong ;)
 
That seems like a good pile of mud to play with :) - seems like you have a map to start with.

How much to read? Line seems like a safe start ...

Any value in shifting two bits from 18/19 to 22/23 to enable Wire(1)?

What is the total image size in bytes? How will the sketch 'tend to' unload the read data for use? More DMA PSRAM for storage (Flash?) or display? Dump to SD card? Have to avoid doubled DMA's ? Especially over QSPI pins.

What does DMA to DTCM look/act like? Wondering about DMA conflicts and copious incoming data when in use - so single frame read?

Having a PCB for the camera/T_4.1/DISPLAY would be awesome :) :rolleyes: - maybe a button or two for picture/freeze - and LiPo power:) Ordering a pair is $8 - but soldering/wiring is an adventure.
 
Hello,

Yes, it the DMA could do the read, even if it has to read 16 bits when only 8 are useful would be a great improvements.
Then at the end of each line, the SF could take this 16 bit line, make it 8 bit and move on... thus saving some ram (if needed)...

With regard to the touchscreen, I think that the best solution would be to do it as part of the screen SPI frame...

Let me explain, at the moment, we use the SPI in write 16 mode, but in fact, you could construct a single 20 or so byte dataset to send to the touchscreen, with associated 20 bytes response. I would envision, at the end of each screen frame sent that the SPI system would switch to the touch stuff, send/receive the 20 bytes and then move on to the next screen frame... This of course can be done asynchronously...

I LOVE your idea of the camera PCB for the Teensy!

Cyrille
 
Morning,

As I mentioned, I do think I will get the DMA to work for the camera.

Display/Touch - I am not sure it is realistic to be able to do DMA operations that work through two SPI devices. That is the contiguous updates works for the display as we setup everything up front, and the we just keep sending the 16 bit pixel values and rely on the fact that when you hit the end of the rectangle of pixels to be updated, set by a CASET and PASET registers, it wraps around back to that beginning of the rectangle. So during this operation we do not touch the CS nor DC states... Trying to add this to the end of frame would imply something would have to change the state of the CS pins to change which device receives the data. Also would require a different DMA operation as we don't actually current retrieve data back from SPI... You can do that as I do that in SPI library, but it is not currently anything needed in the display library... Although I suppose one could find need to do an async pixel read rect...

Note: I am not saying that it is totally impossible, but I am not sure you could directly do it with T4. More likely possible with T3.6, where you can encode the CS pins as part of the stuff sent to PUSHR register for which CS pins are to be controlled by that operation and then both CS pins and DC would need to be hardware CS pins... But with T4.x again you MIGHT be able to do something similar on T4.1, although I have not tried the DMA chain to different sizes and locations. That is you might need to add items to chain that change the TCR register instead of TDR SPI register, and both CS pins would need to be hardware CS pins and hope you don't have to muck with DC of display. There are a few issues with this here: a) unlike T3.x where the hardware CS pin select is a mask, such that more than one hardware CS pin can be asserted.... With T4 TCR register it is an index of which one should be asserted. Then the big rub on T4. There is only one hardware CS pin that was brought out for each SPI buss.. On T4.1 we do have some of that option that on SPI object you have CS=10(first index=0) and pins 37 and 36 (1 and 2)... (T3.5 and 3.2 - DMA chain with different sizes and like did not work, when I tried that a few years ago).

So for my own playing - and hopefully adding some more building blocks that hopefully help out.

so for touch, I put in a PR to allow the library to work on other SPI busses instead of only SPI. So on T4.1 easy to move to using SPI1 or SPI2... T4, requires bottom pins. Also added support to use my FlexSPI code. to allow you to use FlexIO pins. I also personally would use the T-IRQ pin, that would signal when the user is actually touching the display. And only do SPI to it then. Library is already setup to do some of this, where it bails and not need to do SPI.

It will be interesting to see how fast the camera can read a frame. I don't want to bump up the SPI speed yet as my 16 pin Logic Analyzer is not as fast as my Pro8 so it can only run so fast...

But I will probably be doing something real simple, that is to have the DMA read in a frame. As you mentioned, will have the DMA complete cause an ISR to happen which will extract the appropriate 8 bits out and write it into a frame buffer, when it completes a full frame, I will then tell the display to update async once from that frame buffer, and change to having the camera update a second frame buffer, which toggles back and forth....

Later will play with touch. Probably would start off with when the user is touching the display the camera does not update the screen. Again it will be interesting to see how fast the screen updates are versus the capture speed. It may turn out that camera updating the frame buffer may update more than once before we change screens, or do we allow it to do part of one frame and part of another... Will see.

Sorry I wish I knew some additional magic, but...
 
Hello,

No need for magic! don't worry!
I was not suggesting using the DMA to do the CS swap, more along the lines of program DMA for LCD output, Irq on end, swich CS, program DMA for touch read, interrupt, back to square 1. This would mean 2 interrupt per LCD refresh, one for touch, one for screen... But anyhow, this was just an idea, a suggestion, something that others might find helpful...

With regard to the camera, and speeds, it all depends on the needs and frequency used.
At the moment, I am working with a slow 16Mhz clock for the screen as anything higher seems to not work. Hopefully once I move away from wires and start using a PCB, I can increase that speed...
Similary, in my case I do NOT need high frequency update of the camera. getting 2 or 3 frames per second is way enough for me...
But it might be different for others!
What is certain is that any way to get the camera data without having to stop everything for ages would be great. As you can see in my code, I am now allowing for frame drops.

Cyrille
 
Hello,

Well, I finally received my PCB! Yeah! for less than $10, I got 5 PCB (minimum order) shipped to me in around 1.5 weeks...
Thanks to easyeda.com and their sister company. I was able to design, create and route that thing in a couple of hours... even as I know next to nothing about PCB design.

And what a difference it makes. Development is so much easier with a system that does not look like an octopus (or a triántapus? as in 30 legs!) thing that will break the instant you touch it...
Also, with a real PCB, I was able to increase the LCD frequency from 13Mhz (top speed with the wires) to 26Mhz! a 2* gain... and it is very visible!

Anyhow, I have a problem because my screen is now upside down, but not a biggie to solve.

My next step is to add planetary motions with the RTC and then move to the big one... take a night time picture and see if I can see enough stars to find my location!
This might mean that I have to work with the camera settings to tune things up and is most likely going to be the hardest part of the system.

some pictures:
IMG_1855.jpg IMG_1856.jpg

Cyrille
 
@cyrille - Yes having a board does make it easier to make sure things like make sure the things like everything stays hooked up...

Sounds like you are having fun.

Yesterday for the heck of it I started playing first with the Arduino library for the camera to try to make it work on T4...

https://github.com/arduino-libraries/Arduino_OV767X

I have a version that compiles and sort of runs, but the images appear to be wrong. Also their code looks like it is reading on the wrong edge of the clock...
As You can see in the LA output:

screenshot.jpg

I used a timing marker to show where it was reading the IO pins. That is the second to bottom is the digitalToggleFast I added
Code:
void OV767X::readFrame(void* buffer)
{
//uint32_t ulPin = 33; // P1.xx set of GPIO is in 'pin' 32 and above
//NRF_GPIO_Type * port;

  //port = nrf_gpio_pin_port_decode(&ulPin);

  noInterrupts();

  uint8_t* b = (uint8_t*)buffer;
  int bytesPerRow = _width * _bytesPerPixel;

  // Falling edge indicates start of frame
  while ((*_vsyncPort & _vsyncMask) == 0); // wait for HIGH
  while ((*_vsyncPort & _vsyncMask) != 0); // wait for LOW
  digitalWriteFast(33, HIGH);
  for (int i = 0; i < _height; i++) {
  // rising edge indicates start of line
    while ((*_hrefPort & _hrefMask) == 0); // wait for HIGH

    for (int j = 0; j < bytesPerRow; j++) {
      // rising edges clock each data byte
      while ((*_pclkPort & _pclkMask) != 0); // wait for LOW

#if defined(__IMXRT1062__)  // Teensy 4.x
      uint32_t in = GPIO6_DR >> 18; // read all bits in parallel
      in = (in & 0x3) | ((in & 0x3f0)>>2);
      digitalToggleFast(32);
#else
      uint32_t in = port->IN; // read all bits in parallel
      in >>= 2; // place bits 0 and 1 at the "bottom" of the register
      in &= 0x3f03; // isolate the 8 bits we care about
      in |= (in >> 6); // combine the upper 6 and lower 2 bits
#endif

      if (!(j & 1) || !_grayscale) {
        *b++ = in;
      }
      while ((*_pclkPort & _pclkMask) == 0); // wait for HIGH
    }
    while ((*_hrefPort & _hrefMask) != 0); // wait for LOW
  }
  digitalWriteFast(33, LOW);

  interrupts();
}
The only changes I made were in the #if... code... And it looked to me like it was going to read on trailing edge of clock instead of leading edge... So will play with it.

Will then hopefully look at DMA... Maybe like the Adafruit version of library? https://github.com/adafruit/Adafruit_OV7670
 
Hello,

The clock polarity is configurable on the camera.
The base code I used is putting the polarity one way, but it can also be the other way around if needed... so it might be that the "standard" library configures it differently.

Cyrille
 
Thanks for the heads up... But my gut tells me the code is wrong here. as:
I changed it to I think look now at leading edge and you can see where the toggle is now, right in the middle of the changes of signals, which I were I think you would want.
screenshot3.jpg

Now I am wondering if the maybe the pixel order or the like are different on their 565 format versus the display...

I have the code currently writing to the ili9341_t3n...
Code:
    Camera.readFrame(pixels);
//    digitalWriteFast(32, LOW);


    int numPixels = Camera.width() * Camera.height();
    int camera_width = Camera.width();

  //for (int i=0; i < numPixels; i++) pixels[i] = ~pixels[i];

    tft.fillScreen(ILI9341_BLACK);
    tft.writeRect(ILI9341_t3n::CENTER, ILI9341_t3n::CENTER, Camera.width(), Camera.height(), pixels);

But there is still some obvious issues... as I think it is missing pixels and the like and ran into next frame...
screenshot2.jpg
Again the bottom line is digitalWrite High/Low around the reading of their readFrame, which they also have disabled interrupts... And you can see channel 8 is where the frame markers are... Still more debugging to go...

Edit: More talking to self... Yep is is missing every other line:
screenshot.jpg
Now to see what I/They are doing wrong here...
Edit again: blue stuff toward bottom is where I am reading in pixels and the red/salmon color like 4 up is where the clock signals are...
 
Hello,

Yep, talking (or writing) one own's thoughts can be weird in a forum:) I have done it a lot of times... and then you are here: should I erase the post? so you remove the most embarrassing part, and there is not much left:)

It seems to me that the 16 bit format is 8 bit reversed between the camera and the screen. So, you can not DMA camera output directly to the screen framebuffer (although I am sure that this is configurable and would be a neat trick!!!!)

Regardless, depending on the camera mode (and pixel count), it looks like you can make it work as 1/2 (or 1/4) format in different ways.
way 1: only take the first 1/2 pixels of each lines and the first 1/2 rows... which seems to be what the default library does.
OR (and that is what my version does), have the camera combine 4 or 16 pixels together to create a single output pixel (ie: the camera does a stretch).

Of course this is better as the whole sensor gets used, not a quarter or a 16th (1/2 resolution is 1/4 surface)...
The other side effect is that in this case, the camera chip will "read" 2 or 4 lines from the sensor and generate 1 output line. So if you look at the lines sync output, you will see a 1/2 or 1/4 duty ratio (does this makes sense)?

Cyrille
 
Hello,

Actually, I think that there is an issue in my code.... But I have no clue where...

The symptom is that when the camera is enabled (under IRQ), sometimes, after a while, things seems to stop, the arduino becomes unresponsive, screen update does not happen anymore and things seems to be blocked...
Sometimes, I see very slow screen being cleared out...

I have no clue what might be happening... maybe IRQ conflict between the LCD and the camera?

Cyrille
 
Hi again,

I fixed (hacked) the above code, to bail out of the last wait if the horizontal goes low. So now gets every line.. Also reversed the bytes and image shows up :D
IMG_1240.jpg
Sorry for poor photo... Also display has been abused for long time so backlight not very strong anymore...

Note: I pushed a WIP branch up on this: https://github.com/KurtE/Arduino_OV767X/tree/Teensy_t4

Will now do quick and dirty hacking of test app, to see how it does trying to read in frame update screen... See how that works.

Will remove the dumping of data and see what it does. May also try removing the enable/disable interrupts code during the reads or maybe only do it per each line...
...

Then try DMA stuff like mentioned earlier.
 
@cyrille and others - Made some progress with the continuous updates stuff, using the library I mentioned...

The loop code is running reasonably quick now:
If I strip out the stuff for one frame... it looks like:
Code:
void loop() {
  if (Serial.available()) {
    int ch = Serial.read();
    while (Serial.read() != -1); // get rid of the rest...
    switch (ch) {
    case 'c':
    {
...
    case 's':
      if (g_continuous_mode) {
        g_continuous_mode = false;
        Serial.println("*** Continuous mode turned off");
        tft.useFrameBuffer(false);
      } else {
        g_continuous_mode = true;
        tft.useFrameBuffer(true);
        Serial.println("*** Continuous mode turned on");
        g_emCycle = 0;
      }
      break;
    }
  }

  if (g_continuous_mode) {
    Camera.readFrame(pixels);
    int numPixels = Camera.width() * Camera.height();

    for (int i = 0; i < numPixels; i++) pixels[i] = (pixels[i] >> 8) | (((pixels[i] & 0xff) << 8));
    tft.waitUpdateAsyncComplete();  // wait while any other is pending...
    tft.fillScreen(ILI9341_BLACK);
    tft.writeRect(ILI9341_t3n::CENTER, ILI9341_t3n::CENTER, Camera.width(), Camera.height(), pixels);
    tft.updateScreenAsync(); // start an async update...
    Serial.printf("Cycle time: %d\n", (uint32_t)g_emCycle);
    g_emCycle = 0;
  }
}

So again nothing special Also not doing any touch stuff...
Code:
Cycle time: 48
Cycle time: 48
Cycle time: 48
Cycle time: 48
Cycle time: 48
Cycle time: 48
I am asking for 30 frames per second but it is coming in at about 20, can probably fix some more of the underlying clock code, but is working reasonably well for me, especially since I am just doing it for the heck of it.

If anyone wishes to give it a try, I mentioned the github location above, with the one new example sketch. I am using your pins from the other sketch except I dont have my touch pins hooked up the same way you do. But may add some for the heck of it... Although will probably use my new version of the touchscreen using FlexSPI...
 
Hello,

Question, In this case, the Camera.readFrame(pixels); is not under IRQ and does a direct read of the camera, isn't it?

Cyrille
 
That is correct. The code simply reads its logically copies the image to the frame buffer of the display (writeRect) and then starts up a DMA update of the screen... In the current case I could also get rid of the fillScreen as the images are always the same size and in the current configuration size of the screen..
 
Hello,

ok, I am asking because in my IRQ based version, I have the feeling that the camera IRQs are causing (sometimes) an issue with the screen IRQ (or something else)... and I have no clue what and/or how to fix it :-(

Cyrille
 
Yea - I saw your post yesterday.

Not sure if something got out of sync. I did not see anywhere where you set the priority of the interrupt, so I am assuming probably default like 128... So I would think some higher priority tasks would run.

But again wonder if it could starve out other ISRs that are at equal or lower priority. Or if maybe your code detected an error condition and did not setup to recover from it.

The only way I know of finding these is to try to detect where. sometimes can do by strategic Serial.print statements, other times digitalWrite/Toggle... statements.

Of if the main loop still runs, and you can detect like no new frame in Time X or the updateScreen did not complete in Time Y, then try to dump as much information as you can.... With the display I would dump all of the DMA settings data.... With camera stuff, I would dump your logical states, like did I receive an error? And then see if there is something you can do to recover... Or better yet to avoid.

Sorry not much help.

That is one reason I started off trying to Keep it simple...
 
Status
Not open for further replies.
Back
Top