mhelin
Well-known member
Not so good start for the new RP2350 though, problems with GPIO input latch-up:For many applications the Pico would be ideal.
https://github.com/raspberrypi/pico-feedback/issues/401
Not so good start for the new RP2350 though, problems with GPIO input latch-up:For many applications the Pico would be ideal.
32bit floats on an 8bit micro will slow things down a lot
Excellent, that is the way I would prefer to do it. So, can you achieve an 44Kb/s sample rate and do all the floating point math? I know the Pico has some ARM optimised software floating point routines but I do not know how/if an AVR would cope. Have you looked at Hartley transforms?All in software. It's not running as fast as I would like (but looks OK visually) but I have some ideas to optimise it more before giving up and moving to a faster micro. I don't have the PCB space for external rectifier circuitry and I enjoy a bit of a challenge
I could probably reach 44Kb with 1 or 2 channels but I'm trying to do 5 channelsExcellent, that is the way I would prefer to do it. So, can you achieve an 44Kb/s sample rate and do all the floating point math? I know the Pico has some ARM optimised software floating point routines but I do not know how/if an AVR would cope. Have you looked at Hartley transforms?
Cheers
Ian
I've "some" experience of analogue and digital CCTV, video recording, MUX, transmission, storage, blah, and 25 IPS* is effectively from the UK broadcast TV standard which gives fairly fluid motion, especially with a bit of afterglow in the phosphor ... although it's less good when you're watching a fast car or tennis on an LED display. In the 'States, unsurprisingly, 30 rather than 25 was adopted as the de facto "real time" standard. Since IP video no one needs to be wedded to these and provided you *don't* capture at the same frequency as (or 2nd harmonic of) the AC lighting power you shouldn't suffer flicker or moiré effect.25Hz is roughly the number of frames per second to trick our eyes into perceiving motion.
I used that chip. Worked great.Has anyone used the MAX 7219/7221 LED drivers for audio meters? In theory one chip could do 8 bars graphs of 8 LEDs each or 4 of`16 each. Ideal for bus meters? Ans still available in a DIP package!
Cheers
Ian
mled32.h
--
#ifdef __cplusplus
extern "C" {
#endif
#define BIT_MASK(n) (1ul << (n))
#define BIT_ISSET(p,n) (((p) & (1ul << (n))) ? 1 : 0)
#define BIT_SET(p,n) ((p) |= (1ul << (n)))
#define BIT_UNSET(p,n) ((p) &= ~(1ul << (n)))
#define BIT_FLIP(p,n) ((p) ^= (1ul << (n)))
#define MLED32_DIG0 0
#define MLED32_DIG1 1
#define MLED32_DIG2 2
#define MLED32_DIG3 3
#define MLED32_DIG4 4
#define MLED32_DIG5 5
#define MLED32_DIG6 6
#define MLED32_DIG7 7
#define MLED32_SEG0 0
#define MLED32_SEG1 1
#define MLED32_SEG2 2
#define MLED32_SEG3 3
#define MLED32_SEG4 4
#define MLED32_SEG5 5
#define MLED32_SEG6 6
#define MLED32_SEG7 7
#define MLED32_SEGG 0
#define MLED32_SEGF 1
#define MLED32_SEGE 2
#define MLED32_SEGD 3
#define MLED32_SEGC 4
#define MLED32_SEGB 5
#define MLED32_SEGA 6
#define MLED32_SEGDP 7
typedef uint8_t mled32_shared_t[8];
struct mled32_led {
uint8_t bit;
uint8_t dig;
uint8_t seg;
};
struct mled32 {
mled32_shared_t *shared;
struct mled32_led *leds;
uint8_t nleds;
uint8_t pin_cs;
uint32_t mask;
uint32_t curr;
};
int max7221_reset(uint8_t pin_cs,
uint8_t intensity,
uint8_t scanlimit);
int max7221_test(uint8_t pin_cs, int op);
int mled32_init(struct mled32 *ml,
mled32_shared_t *shared,
uint8_t pin_cs,
struct mled32_led *leds,
uint8_t nleds);
int mled32_write(struct mled32 *ml, uint32_t bval);
#ifdef __cplusplus
}
#endif
mled32.cpp
--
#include <SPI.h>
#include "mled32.h"
SPISettings max7221(10000000, MSBFIRST, SPI_MODE0);
int
max7221_reset(uint8_t pin_cs,
uint8_t intensity,
uint8_t scanlimit)
{
uint8_t data[][2] = {
{ 0x01, 0x00 },
{ 0x02, 0x00 },
{ 0x03, 0x00 },
{ 0x04, 0x00 },
{ 0x05, 0x00 },
{ 0x06, 0x00 },
{ 0x07, 0x00 },
{ 0x08, 0x00 },
{ 0x0a, intensity }, // intensity
{ 0x0b, scanlimit }, // scanlimit
{ 0x0c, 0x01 }, // shutdown
};
int di, dn;
dn = sizeof(data) / sizeof(data[0]);
SPI.beginTransaction(max7221);
for (di = 0; di < dn; di++) {
digitalWrite(pin_cs, LOW);
SPI.transfer(data[di][0]);
SPI.transfer(data[di][1]);
digitalWrite(pin_cs, HIGH);
}
SPI.endTransaction();
return 0;
}
int
max7221_test(uint8_t pin_cs, int op)
{
if (op < 2) {
int di;
SPI.beginTransaction(max7221);
for (di = 0; di < 8; di++) {
digitalWrite(pin_cs, LOW);
SPI.transfer(0x01 + di);
SPI.transfer(op ? 0xff : 0x00);
digitalWrite(pin_cs, HIGH);
}
SPI.endTransaction();
} else if (op == 2) {
static int dii = 0;
static int sii = 0;
int di;
if (sii == 8) {
sii = 0;
dii++;
}
if (dii == 8)
dii = 0;
SPI.beginTransaction(max7221);
for (di = 0; di < 8; di++) {
digitalWrite(pin_cs, LOW);
SPI.transfer(0x01 + di);
SPI.transfer(di == dii ? BIT_MASK(sii) : 0x00);
digitalWrite(pin_cs, HIGH);
}
SPI.endTransaction();
sii++;
} else if (op == 3) {
static int intensity = 0;
static int updown = 1;
SPI.beginTransaction(max7221);
digitalWrite(pin_cs, LOW);
SPI.transfer(0x0a);
SPI.transfer(intensity & 0xF);
digitalWrite(pin_cs, HIGH);
SPI.endTransaction();
//Serial.println(intensity, HEX);
intensity += updown;
if (intensity == 0 || intensity == 15)
updown *= -1;
}
return 0;
}
int
mled32_write(struct mled32 *ml, uint32_t bval)
{
uint32_t trans;
int li, di;
struct mled32_led *ld;
uint8_t dig_updated = 0;
trans = ml->curr ^ bval & ml->mask;
for (li = 0; li < ml->nleds; li++) {
ld = &ml->leds[li];
if (BIT_ISSET(trans, ld->bit) == 0) {
continue;
}
BIT_FLIP(ml->curr, ld->bit);
BIT_FLIP((*ml->shared)[ld->dig], ld->seg);
BIT_SET(dig_updated, ld->dig);
}
SPI.beginTransaction(max7221);
for (di = 0; dig_updated; di++) {
if (dig_updated & 1) {
digitalWrite(ml->pin_cs, LOW);
SPI.transfer(0x01 + di);
SPI.transfer((*ml->shared)[di]);
digitalWrite(ml->pin_cs, HIGH);
}
dig_updated >>= 1;
}
SPI.endTransaction();
return 0;
}
int
mled32_init(struct mled32 *ml,
mled32_shared_t *shared,
uint8_t pin_cs,
struct mled32_led *leds,
uint8_t nleds)
{
int li;
struct mled32_led *ld;
uint32_t mask = 0;
memset(ml, 0, sizeof(*ml));
memset(shared, 0, sizeof(*shared));
ml->shared = shared;
ml->pin_cs = pin_cs;
ml->leds = leds;
ml->nleds = nleds;
for (li = 0; li < ml->nleds; li++) {
ld = &ml->leds[li];
BIT_SET(mask, ld->bit);
}
ml->mask = mask;
pinMode(pin_cs, OUTPUT);
return 0;
}
Good to hear someone has used it and many thanks for the example code which answers a lot of detailed questions. I have an Arduino board somewhere - I will have a play.I used that chip. Worked great.
Here's some Arduino code:
Yeah same idea here with the simplified 263X"dbx used the same LED meter scheme for all of the 900 series units on a sub board"
- suspect this is the same as used on the dbx 160X / XT / A. On the X and XT it was a piggy-back board. When a driver chip fails a block of LEDs goes out and a little sleuthing pinpoints the relevant one
Enter your email address to join: