Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Carla Guo
Published © GPL3+

Performance Compare: XIAO RP2040 VS XIAO RP2350

Use a pair of round displays to compare the performance of the XIAO RP2040 and XIAO RP2350.

IntermediateFull instructions provided1 hour1,971

Things used in this project

Story

Read more

Schematics

XIAO RP2350 Schematic file

Code

pin_arduino.h

C/C++
Arduino pin_arduino.h file for XIAO RP2350
#pragma once

// Pin definitions taken from:
//    https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf


// LEDs
#define PIN_LED        (25u)

// Digital pins
static const uint8_t D0 = (26u);
static const uint8_t D1 = (27u);
static const uint8_t D2 = (28u);
static const uint8_t D3 = (5u);
static const uint8_t D4 = (6u);
static const uint8_t D5 = (7u);
static const uint8_t D6 = (0u);
static const uint8_t D7 = (1u);
static const uint8_t D8 = (2u);
static const uint8_t D9 = (4u);
static const uint8_t D10 = (3u);
static const uint8_t D11 = (21u);
static const uint8_t D12 = (20u);
static const uint8_t D13 = (17u);
static const uint8_t D14 = (16u);
static const uint8_t D15 = (11u);
static const uint8_t D16 = (12u);
static const uint8_t D17 = (10u);
static const uint8_t D18 = (9u);

// Analog pins
static const uint8_t A0  = (26u);
static const uint8_t A1  = (27u);
static const uint8_t A2  = (28u);
static const uint8_t A3  = (5u);
static const uint8_t A4 = (6u);
static const uint8_t A5 = (7u);
static const uint8_t A6 = (0u);
static const uint8_t A7 = (1u);
static const uint8_t A8 = (2u);
static const uint8_t A9 = (4u);
static const uint8_t A10 = (3u);
#define ADC_RESOLUTION 12

// NeoPixel
#define PIN_NEOPIXEL   (22u)
#define NEOPIXEL_POWER (23u)

// BAT PIN
#define BAT_DET_PIN (29u)
#define BAT_READ_EN (19u)

// Serial1
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)

// Serial2 
#define PIN_SERIAL2_TX (20u)
#define PIN_SERIAL2_RX (21u)

// SPI
#define PIN_SPI0_MISO  (4u)
#define PIN_SPI0_MOSI  (3u)
#define PIN_SPI0_SCK   (2u)
#define PIN_SPI0_SS    (5u) // not pinned out
static const uint8_t SS   = PIN_SPI0_SS;   // SPI Slave SS not used. Set here only for reference.
static const uint8_t MOSI = PIN_SPI0_MOSI;
static const uint8_t MISO = PIN_SPI0_MISO;
static const uint8_t SCK  = PIN_SPI0_SCK;

#define PIN_SPI1_MISO  (12u)
#define PIN_SPI1_MOSI  (11u)
#define PIN_SPI1_SCK   (10u)
#define PIN_SPI1_SS    (9u)
#define SPI1_MISO       (PIN_SPI1_MISO)
#define SPI1_MOSI       (PIN_SPI1_MOSI)
#define SPI1_SCK        (PIN_SPI1_SCK)

// Wire
#define PIN_WIRE0_SDA  (16u)
#define PIN_WIRE0_SCL  (17u)

#define PIN_WIRE1_SDA  (6u)
#define PIN_WIRE1_SCL  (7u)
#define SDA            PIN_WIRE1_SDA
#define SCL            PIN_WIRE1_SCL
#define I2C_SDA        (SDA)
#define I2C_SCL        (SCL)

#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY    (2u)
#define WIRE_HOWMANY   (2u)

// #include "../generic/common.h"

Compare with tft.drawPixel( );

C/C++
#include <TFT_eSPI.h>   // Include the TFT_eSPI library

TFT_eSPI tft = TFT_eSPI();  // Create TFT_eSPI object

const int screenWidth = 240;  // Screen width
const int screenHeight = 240; // Screen height

unsigned long startTime;
float totalTime = 0;
float averageFPS;
float fillFPS;
const int colorCount = 6;  // Total colors to fill

void setup() {
  Serial.begin(115200);  // Initialize serial for output
  tft.init();            // Initialize TFT screen
  tft.fillScreen(TFT_BLACK);  // Set initial screen color to black
}

void fillScreenAndMeasure(uint16_t color) {
  startTime = millis();  // Record start time
  for (int y = 0; y < screenHeight; y++) {
    for (int x = 0; x < screenWidth; x++) {
      tft.drawPixel(x, y, color);  
    }
  } // Fill the screen with the specified color
  unsigned long fillTime = millis() - startTime;  // Calculate fill time
  fillFPS = 1000.0 / fillTime;  // Calculate FPS
  totalTime += fillTime;  // Accumulate total time

  // Output fill time and FPS
  Serial.print("Fill time (ms): ");
  Serial.println(fillTime);
  Serial.print("Fill FPS: ");
  Serial.println(fillFPS);
}

void loop() {
  // Fill screen with 6 different colors
  fillScreenAndMeasure(TFT_RED);
  fillScreenAndMeasure(TFT_BLUE);
  fillScreenAndMeasure(TFT_GREEN);
  fillScreenAndMeasure(TFT_YELLOW);
  fillScreenAndMeasure(TFT_BLACK);
  fillScreenAndMeasure(TFT_WHITE);

  // Calculate average FPS
  averageFPS = (1000.0 * colorCount) / totalTime;

  // Output total time and average FPS
  Serial.print("Total fill time (ms): ");
  Serial.println(totalTime);
  Serial.print("Average FPS: ");
  Serial.println(averageFPS);

  // Display total time and average FPS on the screen
  tft.setTextColor(TFT_BLACK);  // Set text color to black
  tft.setTextSize(2);            // Set text size

  tft.setCursor(10, 90);         // Set text position
  tft.print("XIAO RP2350");      // Use xiao_rp2350
  // tft.print("XIAO RP2040");    // Use xiao_rp2040

  tft.setCursor(10, 115);        // Set text position
  tft.print("Total time: ");
  tft.print(totalTime);
  tft.println(" ms");

  tft.setCursor(10, 150);        // Adjust position slightly
  tft.print("Avg FPS: ");
  tft.print(averageFPS);

  delay(5000);  // Wait before repeating measurement

  totalTime = 0;  // Reset total time
}

Compare with Gray conversion

C/C++
#include "rp_test.c"      // Include the test image data
#include <TFT_eSPI.h>     // Include the TFT_eSPI library

#define WIDTH 240         // Image width
#define HEIGHT 180        // Image heigh

uint8_t grayImage[WIDTH * HEIGHT];   // Grayscale image array
uint16_t rgb565Image[WIDTH * HEIGHT]; // RGB565 image array

uint16_t rgb565; // Variable for storing RGB565 pixel data
uint8_t r, g, b; // RGB components
uint8_t gray;    // Grayscale value

TFT_eSPI tft = TFT_eSPI(); // Create TFT_eSPI object

// Convert RGB565 to grayscale
void RGB565ToGray() {
    for (int i = 0; i < WIDTH * HEIGHT; i++) {
        rgb565 = (gImage_rp_test[i * 2] << 8) | gImage_rp_test[i * 2 + 1];
        r = (rgb565 >> 11) & 0x1F;   // Extract 5 bits for Red
        g = (rgb565 >> 5) & 0x3F;    // Extract 6 bits for Green
        b = rgb565 & 0x1F;           // Extract 5 bits for Blue

        // Scale RGB values to 0-255
        r = (r * 255) / 31;
        g = (g * 255) / 63;
        b = (b * 255) / 31;

        // Calculate grayscale value using luminance formula
        grayImage[i] = (r * 77 + g * 150 + b * 29) >> 8;
    }
}

// Convert grayscale to RGB565 format
void GrayToRGB565() {
    for (int i = 0; i < WIDTH * HEIGHT; i++) {
        gray = grayImage[i]; // Get grayscale value (0-255)
        // Convert grayscale to RGB565 format
        uint16_t r = (gray >> 3) & 0x1F;  // 5 bits for red
        uint16_t g = (gray >> 2) & 0x3F;  // 6 bits for green
        uint16_t b = (gray >> 3) & 0x1F;  // 5 bits for blue

        // Combine into 16-bit RGB565 format
        rgb565Image[i] = (r << 11) | (g << 5) | b;
    }
}

// Display the RGB565 image on the screen
void displayImage() {
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            // Each pixel is 2 bytes (16-bit RGB565)
            int index = (y * WIDTH + x) * 2;
            rgb565 = (gImage_rp_test[index] << 8) | gImage_rp_test[index + 1];
            tft.drawPixel(x, y + 30, rgb565); // Draw pixel 
        }
    }
}

// Display the grayscale image on the screen
void displayGrayImage() {
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            int index = (y * WIDTH + x);
            tft.drawPixel(x, y + 30, rgb565Image[index]); // Draw grayscale pixel
        }
    }
}

void setup() {
    tft.init();            // Initialize TFT screen
}

void loop() {
    // Display the original RGB565 image
    displayImage();
    delay(500);
    tft.fillScreen(TFT_WHITE); // Clear screen to white
    delay(500);

    // Measure the time taken for grayscale conversion
    unsigned long start = micros();
    RGB565ToGray();           // Convert RGB565 to grayscale
    unsigned long duration = micros() - start; // Measure duration
    GrayToRGB565();          // Convert grayscale to RGB565 format
    displayGrayImage();      // Display the grayscale image

    delay(500);
    tft.fillScreen(TFT_WHITE);  // Clear screen again

    // Display information on the screen
    tft.setTextColor(TFT_BLACK);  // Set text color to black
    tft.setTextSize(2);            // Set text size
    tft.setCursor(30, 50);         // Set cursor position
    tft.print("XIAO RP2350");      // Use xiao_rp2350
    // tft.print("XIAO RP2040");    // Use xiao_rp2040

    tft.setCursor(30, 80);         
    tft.print("Image size:");
    tft.setCursor(30, 100);        
    tft.print("240*180");
    tft.setCursor(30, 130);        
    tft.print("Gray conversion");
    tft.setCursor(30, 150);        
    tft.print("time (us): ");
    tft.print(duration);
    
    delay(5000);  // Wait before repeating
}

Credits

Carla Guo

Carla Guo

1 project • 2 followers

Comments