Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDRAM Examples #38

Open
rdockterjr opened this issue Aug 10, 2020 · 17 comments
Open

SDRAM Examples #38

rdockterjr opened this issue Aug 10, 2020 · 17 comments
Labels
documentation Improvements or additions to documentation enhancement New feature or request question Further information is requested

Comments

@rdockterjr
Copy link

I've noticed the Portenta_SDRAM library: https://github.com/arduino/ArduinoCore-mbed/tree/master/libraries/Portenta_SDRAM
But it does not have an examples folder. It would be very helpful if someone could post a basic read/write example for interacting with the external SDRAM.

@facchinm
Copy link
Member

@rdockterjr you are right, a tutorial on external ram usage is coming.
In the meantime, you can take a look at https://github.com/arduino/ArduinoCore-mbed/blob/master/libraries/doom/doomgeneric_arduino.cpp#L198 for a sample use.
After initializing the RAM via SDRAM.begin(start_address) you can call SDRAM.malloc() and SDRAM.free() from C++ code or ea_malloc and ea_free from C code and it will transparently use the external ram as storage.

@facchinm facchinm added documentation Improvements or additions to documentation enhancement New feature or request question Further information is requested labels Aug 12, 2020
@facchinm
Copy link
Member

@sbhklr

@rdockterjr
Copy link
Author

rdockterjr commented Aug 12, 2020

@facchinm Thanks for the feedback. Just to clarify the preferred usage method would be as follows:
int *array;
array = (int *)SDRAM.malloc(100);
Which would give me an array of size 100 on the SDRAM chip. As opposed to the access method in test():
uint8_t *const sdramptr = (uint8_t*)SDRAM_START_ADDRESS;
Which would just give me a pointer to the first location in SDRAM. Which I could then use directly? Would this way be more efficient?

@facchinm
Copy link
Member

Using the wrapped malloc allows you to forget about allocations as they are entirely handled by the library, so that's the best way unless you need some specific location (for example to allocate a large contiguous area like a framebuffer).

@aentinger
Copy link
Contributor

I'm closing this as no further reply by @rdockterjr came in. Please reopen and continue the discussion if necessary.

@hpssjellis
Copy link
Contributor

hpssjellis commented Oct 2, 2021

@aentinger

Can we open this up again?

What would be incredibly useful would be an example assigning the Camera 320x320 Grayscale frame buffer to SDRAM for the Portenta Vision Shield.

Here is a link to the present Portenta raw data example

https://github.com/arduino/ArduinoCore-mbed/blob/master/libraries/Portenta_Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino

By the way a grayscale OLED is the only way to mess around with the Portenta Vision Shield (I use the WaveShare 1.5 inch Grayscale 128x128 using the library Adafruit_SSD1327.h)

image

I would submit a PR for you if the SDRAM 320x320 camera example worked.

I have a base example here for using the grayscale OLED with the Portenta camera, it just needs the SDRAM coding.

@hpssjellis
Copy link
Contributor

hpssjellis commented Oct 2, 2021

Surprisingly this works here with camera at 320x320 and the OLED is very fast showing the screen, using SDRAM for the camera frame buffer.

@facchinm

but I feel it will eventually have memory leaks. Can someone make a suggestion as to how to make it a bit more robust. Specifically how to align it 16 or 32 bit whatever makes more sense. When I use the below method with a machine learning program it randomly crashes. I think align 32 is the best bet but don't know how to do that. The follwoing is probably the main line of code

  sdram_frame_buffer = (uint8_t *)mySDRAM.malloc(320 * 320 * sizeof(uint8_t));
/*
 * 
 *
 * Purchase here https://www.waveshare.com/1.5inch-OLED-Module.htm about $29 USD
 *
 * Note u8g2 is an arduino search caplble library, easy to install
 *
 *  using 128 x 64 seeeduino OLED
 *  black GND 
 *  red 3v3      so do not need the protective resistors below
 *  //white SDA    D11 // on portenta
 *  //yellow SCL   D12 // on portenta
 *  
 *  FOR the GRAYSCALE Waveshare OLED
 *   blue  DIN (mosi) D8
 *   yellow (sck) D9 
 *   orange (cs) D7
 *   green (dc)  D6
 *   white (reset) not needed but D14 if you did
 *
 * another reference here 
 * https://learn.adafruit.com/adafruit-gfx-graphics-library/graphics-primitives
 *
 */


#include <Arduino.h>  // only needed for https://platformio.org/
#include <SDRAM.h>
#include <Adafruit_SSD1327.h>

// Used for software SPI
#define OLED_CLK D9  //yellow wire
#define OLED_MOSI D8 // blue wire 

// Used for software or hardware SPI
#define OLED_CS D7  // orange wire
#define OLED_DC D6   // green wire 

// Used for I2C or SPI
#define OLED_RESET -1

// hardware SPI
Adafruit_SSD1327 display(128, 128, &SPI, OLED_DC, OLED_RESET, OLED_CS);


#include "camera.h"

CameraClass cam;

SDRAMClass mySDRAM;

uint8_t *sdram_frame_buffer;
//uint8_t frame_buffer[320*320];

void setup() {
  //Serial.begin(921600);  
  Serial.begin(115200);  
 
  //mySDRAM.begin();
  
  mySDRAM.begin(SDRAM_START_ADDRESS);

  
  sdram_frame_buffer = (uint8_t *)mySDRAM.malloc(320 * 320 * sizeof(uint8_t));
 
  // Init the cam QVGA, 30FPS
  cam.begin(CAMERA_R320x320, 30);

    if ( ! display.begin(0x3D) ) {
     Serial.println("Unable to initialize OLED");
     while (1) yield();
  }    
    display.setTextSize(1);
    display.setTextColor(SSD1327_WHITE);

    display.setRotation(0);
    display.setCursor(0,0);

    
}

void loop() {
    display.clearDisplay();                 // clear the internal memory

  
   //  display.drawPixel(random(128), random(128), random(512)); 
  // Wait until the receiver acknowledges
  // that they are ready to receive new data
  //while(Serial.read() != 1){};
  
  // Grab frame and write to serial
  if (cam.grab(sdram_frame_buffer) == 0) {
     //Serial.write(frame_buffer, 320*320);     


    for (int x=0; x < 320; x++){     // FRAME_BUFFER_COLS = 320
       for (int y=0; y < 320; y++){       //FRAME_BUFFER_ROWS = 320

          uint16_t myGRAY = sdram_frame_buffer[(y * 320) + x] ;  
        //  int myGRAY = frame_buffer[(y * 320) + x] ;  

        
          int myGrayMap = map(myGRAY, 0, 255, 0, 15);  
          int xMap = map(x, 0, 320, 0, 127);
          int yMap = map(y, 0, 320, 0, 127);
     //     display.drawPixel(xMap, yMap, myGRAY); 
           display.drawPixel(xMap, yMap, (int)myGrayMap);   // grayscale 0-16, 128x128  //128 x 64
         // delayMicroseconds(10);
      } 
    }     
  }

      display.drawRect(5,5,120,120, SSD1327_WHITE );

    display.setCursor(10,10);
    display.println("Rocksetta");

    
  display.display();
        
 // delay(100); 
}

@aentinger aentinger reopened this Oct 4, 2021
@hpssjellis
Copy link
Contributor

Extra question for working with Tensorflowlite.
Here is an unsigned char array that stores a potentially very large machine learning model. How can I assign the char array to SDRAM and 32 or 16 bit align it?

unsigned int model_tflite_len = 2640;
const unsigned char model_tflite[] = { ...}

@hpssjellis
Copy link
Contributor

Ok, with some help from the people at EdgeImpulse.com I got the alignment working for the camera here

The key parts are

#define ALIGN_PTR(p,a)   ((p & (a-1)) ?(((uintptr_t)p + a) & ~(uintptr_t)(a-1)) : p)


SDRAMClass mySDRAM;

uint8_t *sdram_frame_buffer; // 32-byte aligned
static uint8_t *ei_camera_frame_mem;

then in setup


    ei_camera_frame_mem = (uint8_t *) SDRAM.malloc(320 * 320 + 32 /*alignment*/);
    sdram_frame_buffer = (uint8_t *)ALIGN_PTR((uintptr_t)ei_camera_frame_mem, 32);

and this method works without errors with a machine learning model.

Still curious about the above tensorflwolite question.

@hpssjellis
Copy link
Contributor

@facchinm @petewarden

I put a question on stackoverflow here

basically about assigning data directly to an SDRAM block of memory, instead of making a normal array and then assigning the pointer to the array. Here is working code for the Arduino Portenta. Any suggestions?


// Needed for SDRAM assignment on Arduino Portenta
#include <SDRAM.h>
#define ALIGN_PTR(p,a)   ((p & (a-1)) ?(((uintptr_t)p + a) & ~(uintptr_t)(a-1)) : p)
SDRAMClass mySDRAM;



// assign values to a regular array
unsigned char model_tflite[] = {0x54, 0x46, 0x4c, 0x33};
unsigned int model_tflite_len = 4;



// define SDRAM pointer
unsigned char *sdram_mem;
unsigned char *sdram_tflite; // 32-byte aligned




void setup() {
   Serial.begin(115200);
   mySDRAM.begin(SDRAM_START_ADDRESS);   

   // setup SDRAM memory block
   sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
   sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);

   // THE PROBLEM
   // How to assign the data directly to the allocated memory
   // without having to make the actual array
   // The following line works
   // sdram_tflite = model_tflite;

   // This line doesn't work
   // sdram_tflite =  {0x54, 0x46, 0x4c, 0x33};
 
   // The following works, but is very clumsy 
   *(sdram_tflite + 0) =  0x54;
   *(sdram_tflite + 1) =  0x46;
   *(sdram_tflite + 2) =  0x4c;
   *(sdram_tflite + 3) =  0x33;
   
   
}

void loop() {
  Serial.println("Regular Array");
   for (int i=0; i < model_tflite_len; i++){
     Serial.println(model_tflite[i], HEX);
   }   
   
  Serial.println("SDRAM pointer as an array");
   for (int i=0; i < model_tflite_len; i++){
     //Serial.println( "-" );
     Serial.println( *(sdram_tflite + i), HEX );
   }
   Serial.println("--------------------");
   Serial.println();
   delay(4000);
}

@metanav
Copy link

metanav commented Oct 28, 2021

I don't have Portenta but I guess storing TFLite model into flash (const array) and load into SDRAM memory at runtime should work.

const unsigned char model_tflite[] = {0x54, 0x46, 0x4c, 0x33};
unsigned int model_tflite_len = 4;
unsigned char *sdram_mem;
unsigned char *sdram_tflite; // 32-byte aligned

setup() {
   mySDRAM.begin(SDRAM_START_ADDRESS);   
   sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
   sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);
   sdram_tflite = (unsigned char *) model_tflite;
}

@petewarden
Copy link

Hi @hpssjellis! I'm not familiar with the sdram class used by mbed, but would a memcpy() (equivalent to the 'clumsy' approach above, but with a single function call) work? Something like:

   sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
   sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);
   memcpy(sdram_tflite, model_tflite, model_tflite_len);

@hpssjellis
Copy link
Contributor

hpssjellis commented Oct 29, 2021

Thanks for replying @petewarden, and I was wondering how to use memcpy, but that solution still has the data first being entered into a regular array. With all the regular array size limits on the portenta < about 1 MB.

I need to enter the data directly into the block of memory allocated by the much larger, up to 8MB SDRAM pointer without first putting the data into an array. I could load the data after compilation from the SD Card but that adds complexity.

Here is my latest working code, almost complete.

// Needed for SDRAM assignment on Arduino Portenta
#include <SDRAM.h>
#define ALIGN_PTR(p,a)   ((p & (a-1)) ?(((uintptr_t)p + a) & ~(uintptr_t)(a-1)) : p)
SDRAMClass mySDRAM;


// assign values to a regular array
unsigned char model_tflite[] = {0x54, 0x46, 0x4c, 0x33};
unsigned int model_tflite_len = 4;


// define SDRAM pointer
unsigned char *sdram_mem;
unsigned char *sdram_tflite; // 32-byte aligned


void setup() {
   Serial.begin(115200);
   mySDRAM.begin(SDRAM_START_ADDRESS);   

   // setup SDRAM memory block
   sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
   sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);

   // THE PROBLEM
   // How to assign the data directly to the allocated pointer memory
   // without having to make an array as well
   // The following traditional line works
   // sdram_tflite = model_tflite;

   // This line doesn't work
   // sdram_tflite =  {0x54, 0x46, 0x4c, 0x33};
 
   // The following works, but is very clumsy 
   *(sdram_tflite + 0) =  0x54;
   *(sdram_tflite + 1) =  0x46;
   *(sdram_tflite + 2) =  0x4c;
   *(sdram_tflite + 3) =  0x33;
    
}


void myShowArray( unsigned char b[], int sizeOfArray ) {
   for ( int k = 0 ; k < sizeOfArray ; k++ ){
     Serial.println(b[k], HEX);
   }
   Serial.println();
}


void myShowPointer( unsigned char *b, int sizeOfArray ) {
   for ( int k = 0 ; k < sizeOfArray ; k++ ){
     Serial.println(*(b + k), HEX);
   }
   Serial.println();
}


void loop() {
   Serial.println("Regular array");
   for (int i=0; i < model_tflite_len; i++){
     Serial.println(model_tflite[i], HEX);
   }   
   Serial.println();
   
   Serial.println("SDRAM pointer as an array");
   for (int i=0; i < model_tflite_len; i++){
     Serial.println( *(sdram_tflite + i), HEX );
   }
   Serial.println();
   
   Serial.println("Regular array passed as an array to the receiving function");
   myShowArray(model_tflite, model_tflite_len);

   Serial.println("Pointer passed as a pointer to the receiving function");
   myShowPointer(sdram_tflite, model_tflite_len);
  
   Serial.println("Pointer passed as an array to the receiving function");
  // myShowArray(*&sdram_tflite, model_tflite_len);
   myShowArray(sdram_tflite, model_tflite_len);
   
   Serial.println("--------------------");
   Serial.println();  
   delay(4000);
}

Which prints out


Regular array
54
46
4C
33

SDRAM pointer as an array
54
46
4C
33

Regular array passed as an array to the receiving function
54
46
4C
33

Pointer passed as a pointer to the receiving function
54
46
4C
33

Pointer passed as an array to the receiving function
54
46
4C
33

--------------------


@hpssjellis
Copy link
Contributor

Hi @hpssjellis! I'm not familiar with the sdram class used by mbed, but would a memcpy() (equivalent to the 'clumsy' approach above, but with a single function call) work? Something like:

   sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
   sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);
   memcpy(sdram_tflite, model_tflite, model_tflite_len);

@petewarden you might have a solution here. It looks like memcpy can take a string of binary data. So I will look into that.

Thanks.


unsigned char buffer[8];
memcpy(buffer,"\x20\x38\x00\x00\x0E\x82\x00\x06",8);

@hpssjellis
Copy link
Contributor

Thanks @petewarden That works great. Should not be hard to reformat the TensorflowLite model header file array to the needed format.

From:

unsigned char model_tflite[] = {0x54, 0x46, 0x4c, 0x33};
unsigned int model_tflite_len = 4;

To:

   memcpy(sdram_tflite, "\x54\x46\x4c\x33", model_tflite_len);


I think we can re-close this issue.

Here is my final test code:


// Needed for SDRAM assignment on Arduino Portenta
#include <SDRAM.h>
#define ALIGN_PTR(p,a)   ((p & (a-1)) ?(((uintptr_t)p + a) & ~(uintptr_t)(a-1)) : p)
SDRAMClass mySDRAM;


// assign values to a regular array
unsigned char model_tflite[] = {0x54, 0x46, 0x4c, 0x33};
unsigned int model_tflite_len = 4;


// define SDRAM pointer
unsigned char *sdram_mem;
unsigned char *sdram_tflite; // 32-byte aligned


void setup() {
   Serial.begin(115200);
   mySDRAM.begin(SDRAM_START_ADDRESS);   

   // setup SDRAM memory block
   sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
   sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);

   // THE PROBLEM
   // How to assign the data directly to the allocated pointer memory
   // without having to make an array as well
   // The following traditional line works
   // sdram_tflite = model_tflite;

   // This line doesn't work
   // sdram_tflite =  {0x54, 0x46, 0x4c, 0x33};



 
   // The following works, but is very clumsy 
   // *(sdram_tflite + 0) =  0x54;
   // *(sdram_tflite + 1) =  0x46;
   // *(sdram_tflite + 2) =  0x4c;
   // *(sdram_tflite + 3) =  0x33;


   // Try this
   // unsigned char buffer[8];
   // memcpy(buffer,"\x20\x38\x00\x00\x0E\x82\x00\x06",8);

   // yes this works fine!
   memcpy(sdram_tflite, "\x54\x46\x4c\x33", model_tflite_len);


   
    
}


void myShowArray( unsigned char b[], int sizeOfArray ) {
   for ( int k = 0 ; k < sizeOfArray ; k++ ){
     Serial.println(b[k], HEX);
   }
   Serial.println();
}


void myShowPointer( unsigned char *b, int sizeOfArray ) {
   for ( int k = 0 ; k < sizeOfArray ; k++ ){
     Serial.println(*(b + k), HEX);
   }
   Serial.println();
}


void loop() {
   Serial.println("Regular array");
   for (int i=0; i < model_tflite_len; i++){
     Serial.println(model_tflite[i], HEX);
   }   
   Serial.println();
   
   Serial.println("SDRAM pointer as an array");
   for (int i=0; i < model_tflite_len; i++){
     Serial.println( *(sdram_tflite + i), HEX );
   }
   Serial.println();
   
   Serial.println("Regular array passed as an array to the receiving function");
   myShowArray(model_tflite, model_tflite_len);

   Serial.println("Pointer passed as a pointer to the receiving function");
   myShowPointer(sdram_tflite, model_tflite_len);
  
   Serial.println("Pointer passed as an array to the receiving function");
  // myShowArray(*&sdram_tflite, model_tflite_len);
   myShowArray(sdram_tflite, model_tflite_len);
   
   Serial.println("--------------------");
   Serial.println();  
   delay(4000);
}

@hpssjellis
Copy link
Contributor

@facchinm Quick question:

By having M7 set SDRAM then using RPC to send that pointer to M4 we have got SDRAM (or regular memory) working from both cores!!!

Problem for some weird reason I have to re-set the M4 SDRAM pointer each loop from M7 instead of just once in setup. That doesn't make much sense to me but is the only way I can get it to work. Why when using this method would M4 SDRAM lose the pointer location. ??? I will try some other methods today.

/* Original by Khoi Hoang (Github @khoih-prog ) and Jeremy Ellis (Github @hpssjellis )
*  
* The serial data should count up as fast as possible 
*  
*  SDRAM or regular memory access from both Portenta Cores
*  For regular ram use malloc instead of SDRAM.malloc
*  Define the SDRAM memory on M7
*  Pass that memory location to M4 using RPC
*  Access / set the data in SDRAM from either core
*  Open the serial monitor to see the numbers increase
*
*/

#include "RPC.h"  // comes with the mbed board installation
#include "SDRAM.h"

#ifdef CORE_CM7    // Start M7 Core programming

int myMicroDelay = 1;   // set same for both cores, and try smaller
uint32_t* myByteSDRAM;
uint32_t myInt32;

void setup() {
  bootM4();
  RPC.begin();    
  Serial.begin(115200);
  
  SDRAM.begin(); // is the same as SDRAM.begin(SDRAM_START_ADDRESS);
  myByteSDRAM = (uint32_t*) SDRAM.malloc(sizeof(myInt32));

  // Good to know the memory location 
  // while (!Serial);                     // this is blocking
  // Serial.print("Address = 0x"); 
  // Serial.println((uint32_t) myByteSDRAM, HEX);

}


void loop(){
  RPC.call("setVar", (uint32_t) myByteSDRAM);

  if (myInt32 != *myByteSDRAM ) {
    myInt32 = *myByteSDRAM ;   
  }
  Serial.println(myInt32);
  // no delay needed as the RPC call is very slow
}

#endif  // Done M7 core programming

// ------------------------------------------------------------------------

#ifdef CORE_CM4  // Start M4 core programming

int myMicroDelay = 7654;       // This delay (microseconds, not milliseconds) needs to match the speed of the slow M7 RPC call
//int myMicroDelay = 34;       // This is kind of the speeds I want to get output counting up by ~1 each time

uint32_t* myByteSDRAM = 0;
uint32_t myCount = 0;


bool setVar(uint32_t mySentPointer){
  myByteSDRAM = (uint32_t*) mySentPointer; 
  return true;
}


void setup() {
  RPC.begin();
  SDRAM.begin(); // is the same as SDRAM.begin(SDRAM_START_ADDRESS);
  RPC.bind("setVar", setVar);
}


void loop() {
  myCount++;

  // Must check to avoid crash
  if (myByteSDRAM != 0){
    *myByteSDRAM = myCount;
  } 
  
  delayMicroseconds(myMicroDelay);

}

#endif  // end M4 Core Programming

@hpssjellis
Copy link
Contributor

If anyone is interested this code works with SDRAM and the new Camera settings for the Portenta with Vision shield and for this example the Waveshare 128x128 Grayscale OLED


/*
 * 
 * Must use portenta with Vision camera and Waveshare Grayscale 128X128 OLED
 * Should be implemented with MBED version greater than 3.0.0
 * Uses SDRAM to save the frame_buffer
 *
 * Purchase here https://www.waveshare.com/1.5inch-OLED-Module.htm about $29 USD
 *
 *
 *  FOR the GRAYSCALE Waveshare OLED
 *   black GND 
 *   red 3v3     
 *   blue  DIN (mosi) D8
 *   yellow (sck) D9 
 *   orange (cs) D7
 *   green (dc)  D6
 *   white (reset) not needed but D14 if you did
 *
 * another reference here 
 * https://learn.adafruit.com/adafruit-gfx-graphics-library/graphics-primitives
 *
 */

 
 
#include <Arduino.h>  // only needed for https://platformio.org/

#include <Adafruit_SSD1327.h>

// Used for software SPI
#define OLED_CLK D9  //yellow wire
#define OLED_MOSI D8 // blue wire 

// Used for software or hardware SPI
#define OLED_CS D7  // orange wire
#define OLED_DC D6   // green wire 

// Used for I2C or SPI
#define OLED_RESET -1

// hardware SPI
Adafruit_SSD1327 display(128, 128, &SPI, OLED_DC, OLED_RESET, OLED_CS);


#include "camera.h"
#include "SDRAM.h"
#include "himax.h"
HM01B0 himax;
Camera cam(himax);
#define IMAGE_MODE CAMERA_GRAYSCALE

/*
Other buffer instantiation options:
  FrameBuffer fb(0x30000000);
  FrameBuffer fb(320,320,2);
*/

FrameBuffer fb;
#define ALIGN_PTR(p,a)   ((p & (a-1)) ?(((uintptr_t)p + a) & ~(uintptr_t)(a-1)) : p)

static uint8_t *ei_camera_frame_mem;
static uint8_t *frame_buffer; // 32-byte aligned

void setup() {
  Serial.begin(115200);  
  SDRAM.begin(SDRAM_START_ADDRESS);
  // Init the cam 
  //cam.begin(CAMERA_R320x320, IMAGE_MODE, 30);
  cam.begin(CAMERA_R320x320, IMAGE_MODE, 60);

  if ( ! display.begin(0x3D) ) {
     Serial.println("Unable to initialize OLED");
     while (1) yield();
  }    
    display.setTextSize(1);
    display.setTextColor(SSD1327_WHITE);

    display.setRotation(0);
    display.setCursor(0,0);

   // set framebuffer to use the SDRAM memory
   ei_camera_frame_mem = (uint8_t *) SDRAM.malloc(320 * 320 + 32 /*alignment*/);
      if(ei_camera_frame_mem == NULL) {
        Serial.println("failed to create ei_camera_frame_mem"); 
    }
    frame_buffer = (uint8_t *)ALIGN_PTR((uintptr_t)ei_camera_frame_mem, 32);
   
}

void loop() {
  display.clearDisplay();                 // clear the internal memory
    
  if (cam.grabFrame(fb, 3000) == 0) {
     // Serial.write(fb.getBuffer(), cam.frameSize());
    fb.setBuffer(frame_buffer); 

    for (int x=0; x < 320; x++){     // FRAME_BUFFER_COLS = 320
       for (int y=0; y < 320; y++){       //FRAME_BUFFER_ROWS = 320
          uint8_t myGRAY = frame_buffer[(y * 320) + x];  

          int myGrayMap = map(myGRAY, 0, 255, 0, 15);  
          int xMap = map(x, 0, 320, 0, 127);
          int yMap = map(y, 0, 320, 0, 127);
          display.drawPixel(xMap, yMap, myGrayMap );   // grayscale 0-255, 128x128  //128 x 64
      } 
    }     
  }

  display.drawRect(0,0,128,128, SSD1327_WHITE ); // border around the screen
  display.setCursor(3,3);
  display.println("Rocksetta");
    
  display.display();
       
}


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

6 participants