Christian Dupaty 10/2021 IS31FL3731 with CHARLEPLEX LED MATRIX adaptation from Adafruit project to ARM MBEB, tested on NUCLEO L073RZ for original project on Arduino see https://learn.adafruit.com/animated-flame-pendant/overview

Dependencies:   mbed

Christian Dupaty 10/2021

IS31FL3731 with CHARLIEPLEX LED MATRIX adaptation from Adafruit project to ARM MBEB, tested on NUCLEO L073RZ

for original project on Arduino see https://learn.adafruit.com/animated-flame-pendant/overview

The program reads the data from an images file and places it alternately on pages 0 and 1 of IS31FL3731

Data structure in data.h :

first byte x1 PF and y1 pf, second byte x2 PF and y2 pf

loop from x1 to x2

loop from y1 to y2

copy from the third byte into the img buffer (144 bytes)

https://os.mbed.com/media/uploads/cdupaty/stm32_flame.jpg

data structure

const uint8_t anim[] = {
  0x00, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x04, 0x0E, 0x19, 0x22, 0x22, 0x17, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x0D, 0x40, 0x99, 0xF2, 0xFF, 0xFF, 0xF4, 0x91, 0x38, 0x0B, 0x01,
  0x00, 0x00, 0x00, 0x16, 0x6B, 0xC6, 0xE5, 0xDB, 0xCF, 0xBC, 0x93, 0x4B,
  0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0xB4, 0xC8, 0xBC, 0xBA,
  0xB8, 0xAD, 0x8A, 0x42, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x0C, 0x40, 0x9D, 0xF4, 0xFF, 0xFF, 0xFF, 0xDB, 0x70, 0x24, 0x06, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x19, 0x26, 0x2C, 0x29,
  0x1D, 0x0F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00

.............................
Revision:
0:eb53bdf2b7eb
Child:
1:81948520c7ed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Oct 05 13:33:00 2021 +0000
@@ -0,0 +1,161 @@
+#include "mbed.h"
+
+//--------------------------------------------------------------------------
+// Animated flame for Adafruit Pro Trinket.  Uses the following parts:
+//   - Pro Trinket microcontroller (adafruit.com/product/2010 or 2000)
+//     (#2010 = 3V/12MHz for longest battery life, but 5V/16MHz works OK)
+//   - Charlieplex LED Matrix Driver (2946)
+//   - Charlieplex LED Matrix (2947, 2948, 2972, 2973 or 2974)
+//   - 350 mAh LiPoly battery (2750)
+//   - LiPoly backpack (2124)
+//   - SPDT Slide Switch (805)
+//
+// This is NOT good "learn from" code for the IS31FL3731; it is "squeeze
+// every last byte from the Pro Trinket" code.  If you're starting out,
+// download the Adafruit_IS31FL3731 and Adafruit_GFX libraries, which
+// provide functions for drawing pixels, lines, etc.  This sketch also
+// uses some ATmega-specific tricks and will not run as-is on other chips.
+//--------------------------------------------------------------------------
+/*
+Christian Dupaty 10/2021
+IS31FL3731 with CHARLEPLEX LED MATRIX adaptation from Adafruit project to ARM MBEB, tested on NUCLEO L073RZ
+for original project on Arduino see https://learn.adafruit.com/animated-flame-pendant/overview
+
+The program reads the data from an image and places it alternately
+on pages 0 and 1 of IS31FL3731
+
+Data structure in data.h
+first byte x1 PF and y1 pf
+second byte x2 PF and y2 pf
+loop from x1 to x2
+     loop from y1 to y2
+         copy from the third byte into the img buffer (144 bytes)
+
+the I2C write method sends the write address then a series of data, the number of data is then specified
+ex: Wire.write (I2C_ADDR, cmd, s); I2C_ADDR address on 8bits, cmd pointer to data to send, s number of data
+*/
+
+#include "data.h"           // Flame animation data
+//#define debug
+#define I2C_ADDR 0xE8       // I2C address of Charlieplex matrix 0x74
+I2C Wire(I2C_SDA, I2C_SCL);
+uint8_t        page = 0;    // Front/back buffer control
+const uint8_t *ptr  = anim; // Current pointer into animation data
+uint8_t        img[9 * 16]; // Buffer for rendering image
+
+//Buffer for I2C write method
+char cmd[200];
+
+// to select register on IS31FL3731, see datasheet page 9
+void pageSelect(uint8_t n)
+{
+    cmd[0]=0xFD;
+    cmd[1]=n;
+    Wire.write(I2C_ADDR,cmd,2);  // attention write method close communications (stop condition is issued)
+}
+
+// SETUP FUNCTION - RUNS ONCE AT STARTUP -----------------------------------
+
+void setup()
+{
+    uint8_t i, p, s;
+
+    s=0;
+    pageSelect(0x0B);               // Access to the Function Registers (page Night)
+    cmd[0]=0;  
+    s++;                     // adress first internal register                    
+    for(i=0; i<=0x0C; i++) 
+    {
+        cmd[i+1]=0x00;
+        if (i==0) cmd[i+1]=0x00; //  0x08 for Auto Frame Play Mode   0x00 for picture mode
+        if (i==0x0A) cmd[i+1]=0xFF;     // all to 0 except shutdown register
+        s++;
+    }
+    Wire.write(I2C_ADDR,cmd,s);  
+
+    for(p=0; p<2; p++) 
+    {
+        s=0;
+        // For each page used (0 & 1)...
+        pageSelect(p);                 // Access the Frame Registers
+        cmd[0]=0;                      // Start from 1st LED control reg
+        s++;
+        for(i=0; i<0xB4; i++) 
+        {
+            if (i<18) cmd[i+1]=0xFF;          // Enable all LEDs (18*8=144)
+            else cmd[i+1]=0x00;             // desable blink and PWM
+            s++;
+        }
+        Wire.write(I2C_ADDR,cmd,s);
+    }
+}
+
+void loop()
+{
+    uint8_t  a, x1, y1, x2, y2, x, y,s;
+#ifdef debug
+    printf("-------------------------------------------------------------\n");
+    printf("start loop\n");
+    printf("-------------------------------------------------------------\n");
+#endif
+    pageSelect(0x0B);    // Function registers
+    cmd[0]=0x01; // Picture Display reg
+    cmd[1]=page;
+    Wire.write(I2C_ADDR,cmd,2);
+
+    page ^= 1; // Flip front/back buffer index
+
+    // Then render NEXT frame.  Start by getting bounding rect for new frame:
+    a = *ptr++;     // New frame X1/Y1
+    if(a >= 144)   // 0x90
+    {
+        // EOD marker? (valid X1 never exceeds 8)
+        ptr = anim;                 // Reset animation data pointer to start
+        a   = *ptr++; // and take first value
+    }
+    x1 = a >> 4;                  // X1 = high 4 bits
+    y1 = a & 0x0F;                // Y1 = low 4 bits
+    a  = *ptr++;                // New frame X2/Y2
+    x2 = a >> 4;                  // X2 = high 4 bits
+    y2 = a & 0x0F;                // Y2 = low 4 bits
+
+    // Read rectangle of data from anim[] into portion of img[] buffer
+    #ifdef debug
+    printf("x1= %d y1= %d x2= %d y2 = %d \n",x1,y1,x2,y2);
+    #endif
+    for(x=x1; x<=x2; x++) {
+        // Column-major
+        for(y=y1; y<=y2; y++) 
+        {
+        img[(x << 4) + y] = *ptr++;
+        #ifdef debug
+        printf("x= %d y= %d data= %d \n",x,y,img[(x << 4) + y]);
+        #endif
+        }
+    }
+
+    // Write img[] to matrix (not actually displayed until next pass)
+    pageSelect(page);    // Select background buffer
+    s=0;
+    cmd[0]=0x24; // First byte of PWM data
+    s++;
+    // copy img buffer to IS31FL3731
+    for(uint8_t j=0; j<144; j++) 
+    {
+            cmd[j+1]=img[j];
+            s++;
+            #ifdef debug
+            printf("j= %d img[j]= %d \n",j,img[j]);
+            #endif
+    }
+    Wire.write(I2C_ADDR,cmd,s);
+    wait_ms(30);
+}
+
+int main()
+{
+    //printf("Simulation flame with IS31FL3731\n\n");
+    setup();
+    
+    while(1) loop();;
+}