LED Matrix matrix.on(pin) = blink?

I took the liberty of extending your plot point function. Here is the complete code.

#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;

 u_int32_t frame [3] = { // Raw frame buffer
  0, 0, 0
};

enum plotAction : uint8_t 
{
  ledOn,
  ledOff,
  ledToggle,
  ledWipe,
  ledFill
};

int count = 100; 

void setup() {
  Serial.begin(57600);
  while (!Serial) ;
   matrix.begin();
}

void loop() {
  count--;
  if(count < 0){
    count = 100;
    plot(frame, 0, 0, ledFill); // comment out the one you don't want to use 
    //plot(frame, 0, 0, ledWipe);
  }
  else {
     plot(frame, random(8), random(12), ledToggle);
     matrix.loadFrame(frame);
     matrix.renderFrame(0);   
  delay(100);

 /* // this section to print out the buffer on each pass
  for(int i=0; i<3; i++){
    Serial.print(frame[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  */
 }
}

void plot(uint32_t frame[3], uint8_t row, uint8_t col, uint8_t type) {
  uint8_t index = row * 12 + col;
  uint32_t field = (1u << 31) >> (index % 32);
  switch(type){
  case(ledOn): 
    frame[index / 32] |= field;
    break;
  case(ledOff):
    frame[index / 32] &= ~field;
    break;
  case(ledToggle):
  frame[index / 32] ^= field;
  break;
  case(ledWipe):
  frame[0] = (u_int32_t) 0;
  frame[1] = (u_int32_t) 0;
  frame[2] = (u_int32_t) 0;
  break;
  case(ledFill):
  frame[0] = (u_int32_t) 0xFFFFFFFF;
  frame[1] = (u_int32_t) 0xFFFFFFFF;
  frame[2] = (u_int32_t) 0xFFFFFFFF;
  break;
  } 
} 

Still not happy about the

matrix.loadFrame(frame);
matrix.renderFrame(0);  

bit, I think there must be a more efficient way of doing this.

Here is a combination of my last sketch and yours. Does the stuff on the callback.

uint32_t animation[1][4] = { { 0, 0, 0, 50 } };


#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;

enum plotAction : uint8_t {
  ledOn,
  ledOff,
  ledToggle,
  ledWipe,
  ledFill
};

int count = 100;

void plot(uint32_t frame[4], uint8_t row, uint8_t col, uint8_t type) {
  uint8_t index = row * 12 + col;
  uint32_t field = 1 << (31 - (index & 0x1f));
  switch (type) {
    case (ledOn):
      frame[index / 32] |= field;
      break;
    case (ledOff):
      frame[index / 32] &= ~field;
      break;
    case (ledToggle):
      frame[index / 32] ^= field;
      break;
    case (ledWipe):
      frame[0] = (u_int32_t)0;
      frame[1] = (u_int32_t)0;
      frame[2] = (u_int32_t)0;
      break;
    case (ledFill):
      frame[0] = (u_int32_t)0xFFFFFFFF;
      frame[1] = (u_int32_t)0xFFFFFFFF;
      frame[2] = (u_int32_t)0xFFFFFFFF;
      break;
  }
}


void matrix_callback() {
  count--;
  if (count < 0) {
    count = 100;
    plot(animation[0], 0, 0, ledFill);  // comment out the one you don't want to use
    //plot(frame, 0, 0, ledWipe);
  } else {
    plot(animation[0], random(8), random(12), ledToggle);
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  while (!Serial && millis() < 5000)
    ;

  // Cycle through the leds directly
  Serial.println("\nDirectly turn on one led at a time");
  for (uint8_t i = 0; i < 96; i++) {
    matrix.on(i);
    delay(25);
  }

  // now do stuff with matrix.
  matrix.setCallback(&matrix_callback);
  matrix.loadSequence(animation);
  matrix.begin();
  matrix.play(true);
}

void loop() {
  //  matrix.on(random(96));
  //  delay(100);
}

Will do. May start off with issues and then maybe do PRs... But there are other areas I would like to work on, like SerialX objects, but that is different story.

Question: what granularity do you want for issues? I know with the IDE2 stuff, they prefer granularity of one issue.

Like:

  1. Move _sequenceDone = true;
    out of if block.
            if(_callBack != nullptr){
                _callBack();
                _sequenceDone = true;
            }
  1. Wondering about:
#define LED_MATRIX_PORT0_MASK       ((1 << 3) | (1 << 4) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 15))
#define LED_MATRIX_PORT2_MASK       ((1 << 4) | (1 << 5) | (1 << 6) | (1 << 12) | (1 << 13))

static void turnLed(int idx, bool on) {
  R_PORT0->PCNTR1 &= ~((uint32_t) LED_MATRIX_PORT0_MASK);
  R_PORT2->PCNTR1 &= ~((uint32_t) LED_MATRIX_PORT2_MASK);
...

What happens if a higher priority interrupt happens, while doing a line:
R_PORT0->PCNTR1 &= ~((uint32_t) LED_MATRIX_PORT0_MASK);
That after it does the read, another ISR happens which lets say changes the state of pin 15 (Wifi version) from input to output or output to input.
After that ISR completes you will then wipe out that change.

Probably won't happen very often, but I have been hit by similar things in the past.

  1. Add a way to if you have turned on the timer and have not set specific frame/sequence to be used, to allow the user code to manipulate the frame data.

  2. Have a way to maybe logically set the data order. For example a way to say, I wish that the frame buffer was 12 bytes of data, in column order. Would be nice for example for scrolling fonts and the like. Where per each frame, you could simply memcpy data from col1 to col 0, and then add in new byte...

  3. Have way to set the timer to some specific speed, like maybe frames per second...

Problem is, having too much fun :smiley:

hey @KurtE

Granularity one is the way to go :slight_smile:

I know that there's some other work going on with the LED Matrix, because text scroll is broken.
If you post issues and PRs in the GH repo the ones working on it will better answer or give directions.

I have been meaning to have some fun with it but have been hit by a dozen other things so I guess fun is over for me :joy:

Helps to be retired :smiley:

First issue:
LED_matrix: move _sequenceDone = true out of if block by KurtE · Pull Request #42 · arduino/ArduinoCore-renesas (github.com)

2nd:
LED_Matrix: possible race condition. · Issue #43 · arduino/ArduinoCore-renesas (github.com)

Will work on some of the others soon.

1 Like

Still not happy about the
matrix.loadFrame(frame);
matrix.renderFrame(0);
bit, I think there must be a more efficient way of doing this.

You can leave out the renderFrame call! See the code here. renderFrame is just

  _currentFrame = frameNumber % _framesCount;
  next();
  _interval = 0;

but loadFrame already does all that.

This has been fascinating reading although way over my head since you all are orders of magnitude above my level.
So not sure which comment exactly to mark as the "solution" but I am trying code out and learning a lot.

So is it possible to virtually "turn on" a matrix LED but reduce the number of times it is 'blinked' per second giving you a few levels of brightness control?

Not quite.
You are limited to turning one LED on and making it bright. But once you set the matrix scanning you can't change the brightness because that depends on not the speed of the refresh but on the duty cycle of the refresh, that is the ratio of on to off time for any LED in the matrix.

This is in effect fixed by the job it is supposed to be doing. That is scanning the whole of the matrix.

It would be possible to refresh just a part of the matrix and have that part brighter than when it is refreshing the whole of the matrix, but we are not considering this as an option yet. Would that be of interest if it were an option?

Thanks, so you can.
I was sure I tried it commented out and it didn't work but I guess I didn't do what I thought I did.