update and test with rpi zero 2
This commit is contained in:
@@ -164,11 +164,13 @@ int chan_num;
|
||||
|
||||
// Convert RGB text string into integer data, for given channel
|
||||
// Return number of data points for this channel
|
||||
int str_rgb(char *s, int rgbs[][LED_NCHANS], int chan) {
|
||||
int str_rgb(char *s, int rgbs[][LED_NCHANS], int chan)
|
||||
{
|
||||
int i = 0;
|
||||
char *p;
|
||||
|
||||
while (chan < LED_NCHANS && i < CHAN_MAXLEDS && hexdig(*s) >= 0) {
|
||||
while (chan < LED_NCHANS && i < CHAN_MAXLEDS && hexdig(*s) >= 0)
|
||||
{
|
||||
rgbs[i++][chan] = strtoul(s, &p, 16);
|
||||
s = *p ? p + 1 : p;
|
||||
}
|
||||
@@ -177,19 +179,24 @@ int str_rgb(char *s, int rgbs[][LED_NCHANS], int chan) {
|
||||
|
||||
// Set Tx data for 8 or 16 chans, 1 LED per chan, given 1 RGB val per chan
|
||||
// Logic 1 is 0.8us high, 0.4 us low, logic 0 is 0.4us high, 0.8us low
|
||||
void set_color(uint32_t rgb, TXDATA_T *txd) {
|
||||
void set_color(uint32_t rgb, TXDATA_T *txd)
|
||||
{
|
||||
int msk;
|
||||
|
||||
// For each bit of the 24-bit RGB values..
|
||||
for (size_t n = 0; n < LED_NBITS; n++) {
|
||||
for (size_t n = 0; n < LED_NBITS; n++)
|
||||
{
|
||||
// Mask to convert RGB to GRB, M.S bit first
|
||||
msk = n == 0 ? 0x800000 : n == 8 ? 0x8000 : n == 16 ? 0x80 : msk >> 1;
|
||||
msk = n == 0 ? 0x800000 : n == 8 ? 0x8000
|
||||
: n == 16 ? 0x80
|
||||
: msk >> 1;
|
||||
// 1st byte or word is a high pulse on all lines
|
||||
txd[0] = (TXDATA_T)0xffff;
|
||||
// 2nd has high or low bits from data
|
||||
// 3rd is a low pulse
|
||||
txd[1] = txd[2] = 0;
|
||||
if (rgb & msk) {
|
||||
if (rgb & msk)
|
||||
{
|
||||
txd[1] = (TXDATA_T)0xffff;
|
||||
}
|
||||
txd += BIT_NPULSES;
|
||||
@@ -198,19 +205,24 @@ void set_color(uint32_t rgb, TXDATA_T *txd) {
|
||||
|
||||
// Set Tx data for 8 or 16 chans, 1 LED per chan, given 1 RGB val per chan
|
||||
// Logic 1 is 0.8us high, 0.4 us low, logic 0 is 0.4us high, 0.8us low
|
||||
void rgb_txdata(int *rgbs, TXDATA_T *txd) {
|
||||
void rgb_txdata(int *rgbs, TXDATA_T *txd)
|
||||
{
|
||||
int i, n, msk;
|
||||
|
||||
// For each bit of the 24-bit RGB values..
|
||||
for (n = 0; n < LED_NBITS; n++) {
|
||||
for (n = 0; n < LED_NBITS; n++)
|
||||
{
|
||||
// Mask to convert RGB to GRB, M.S bit first
|
||||
msk = n == 0 ? 0x800000 : n == 8 ? 0x8000 : n == 16 ? 0x80 : msk >> 1;
|
||||
msk = n == 0 ? 0x800000 : n == 8 ? 0x8000
|
||||
: n == 16 ? 0x80
|
||||
: msk >> 1;
|
||||
// 1st byte or word is a high pulse on all lines
|
||||
txd[0] = (TXDATA_T)0xffff;
|
||||
// 2nd has high or low bits from data
|
||||
// 3rd is a low pulse
|
||||
txd[1] = txd[2] = 0;
|
||||
for (i = 0; i < LED_NCHANS; i++) {
|
||||
for (i = 0; i < LED_NCHANS; i++)
|
||||
{
|
||||
if (rgbs[i] & msk)
|
||||
txd[1] |= (1 << i);
|
||||
}
|
||||
@@ -219,25 +231,30 @@ void rgb_txdata(int *rgbs, TXDATA_T *txd) {
|
||||
}
|
||||
|
||||
// Swap adjacent bytes in transmit data
|
||||
void swap_bytes(void *data, int len) {
|
||||
void swap_bytes(void *data, int len)
|
||||
{
|
||||
uint16_t *wp = (uint16_t *)data;
|
||||
|
||||
len = (len + 1) / 2;
|
||||
while (len-- > 0) {
|
||||
while (len-- > 0)
|
||||
{
|
||||
*wp = __builtin_bswap16(*wp);
|
||||
wp++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return hex digit value, -ve if not hex
|
||||
int hexdig(char c) {
|
||||
int hexdig(char c)
|
||||
{
|
||||
c = toupper(c);
|
||||
return ((c >= '0' && c <= '9') ? c - '0' : (c >= 'A' && c <= 'F') ? c - 'A' + 10 : -1);
|
||||
return ((c >= '0' && c <= '9') ? c - '0' : (c >= 'A' && c <= 'F') ? c - 'A' + 10
|
||||
: -1);
|
||||
}
|
||||
|
||||
// Map GPIO, DMA and SMI registers into virtual mem (user space)
|
||||
// If any of these fail, program will be terminate_smid
|
||||
void map_devices(void) {
|
||||
void map_devices(void)
|
||||
{
|
||||
map_periph(&gpio_regs, (void *)GPIO_BASE, PAGE_SIZE);
|
||||
map_periph(&dma_regs, (void *)DMA_BASE, PAGE_SIZE);
|
||||
map_periph(&clk_regs, (void *)CLK_BASE, PAGE_SIZE);
|
||||
@@ -245,16 +262,19 @@ void map_devices(void) {
|
||||
}
|
||||
|
||||
// Catastrophic failure in initial setup
|
||||
void fail(char *s) {
|
||||
void fail(char *s)
|
||||
{
|
||||
printf(s);
|
||||
terminate_smi(0);
|
||||
}
|
||||
|
||||
// Free memory segments and exit
|
||||
void terminate_smi(int sig) {
|
||||
void terminate_smi(int sig)
|
||||
{
|
||||
int i;
|
||||
printf("Closing\n");
|
||||
if (gpio_regs.virt) {
|
||||
if (gpio_regs.virt)
|
||||
{
|
||||
for (i = 0; i < LED_NCHANS; i++)
|
||||
gpio_mode(LED_D0_PIN + i, GPIO_IN);
|
||||
}
|
||||
@@ -270,7 +290,8 @@ void terminate_smi(int sig) {
|
||||
|
||||
// Initialise SMI, given data width, time step, and setup/hold/strobe counts
|
||||
// Step value is in nanoseconds: even numbers, 2 to 30
|
||||
void init_smi(int ledChan, int ns, int setup, int strobe, int hold) {
|
||||
void init_smi(int ledChan, int ns, int setup, int strobe, int hold)
|
||||
{
|
||||
int width = ledChan > 8 ? SMI_16_BITS : SMI_8_BITS;
|
||||
int i, divi = ns / 2;
|
||||
|
||||
@@ -286,7 +307,8 @@ void init_smi(int ledChan, int ns, int setup, int strobe, int hold) {
|
||||
smi_dcd = (SMI_DCD_REG *)REG32(smi_regs, SMI_DCD);
|
||||
smi_cs->value = smi_l->value = smi_a->value = 0;
|
||||
smi_dsr->value = smi_dsw->value = smi_dcs->value = smi_dca->value = 0;
|
||||
if (*REG32(clk_regs, CLK_SMI_DIV) != divi << 12) {
|
||||
if (*REG32(clk_regs, CLK_SMI_DIV) != divi << 12)
|
||||
{
|
||||
*REG32(clk_regs, CLK_SMI_CTL) = CLK_PASSWD | (1 << 5);
|
||||
usleep(10);
|
||||
while (*REG32(clk_regs, CLK_SMI_CTL) & (1 << 7))
|
||||
@@ -313,7 +335,8 @@ void init_smi(int ledChan, int ns, int setup, int strobe, int hold) {
|
||||
}
|
||||
|
||||
// Set up SMI transfers using DMA
|
||||
void setup_smi_dma(MEM_MAP *mp, int nsamp, TXDATA_T **txdata) {
|
||||
void setup_smi_dma(MEM_MAP *mp, int nsamp, TXDATA_T **txdata)
|
||||
{
|
||||
DMA_CB *cbs = mp->virt;
|
||||
|
||||
*txdata = (TXDATA_T *)(cbs + 1);
|
||||
@@ -331,7 +354,8 @@ void setup_smi_dma(MEM_MAP *mp, int nsamp, TXDATA_T **txdata) {
|
||||
}
|
||||
|
||||
// Start SMI DMA transfers
|
||||
void start_smi(MEM_MAP *mp) {
|
||||
void start_smi(MEM_MAP *mp)
|
||||
{
|
||||
DMA_CB *cbs = mp->virt;
|
||||
|
||||
start_dma(mp, DMA_CHAN, &cbs[0], 0);
|
||||
|
Reference in New Issue
Block a user