tmp: creating specific modules for 8 channels & 16 channels
This commit is contained in:
@@ -7,7 +7,8 @@ RUN apt-get update && \
|
|||||||
gdb-multiarch \
|
gdb-multiarch \
|
||||||
gcc-arm-linux-gnueabihf \
|
gcc-arm-linux-gnueabihf \
|
||||||
g++-arm-linux-gnueabihf \
|
g++-arm-linux-gnueabihf \
|
||||||
binutils-arm-linux-gnueabihf && \
|
binutils-arm-linux-gnueabihf \
|
||||||
|
libclang-dev && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-22
@@ -144,26 +144,6 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bindgen"
|
|
||||||
version = "0.71.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.9.1",
|
|
||||||
"cexpr",
|
|
||||||
"clang-sys",
|
|
||||||
"itertools",
|
|
||||||
"log",
|
|
||||||
"prettyplease",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"rustc-hash",
|
|
||||||
"shlex",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bindgen"
|
name = "bindgen"
|
||||||
version = "0.72.0"
|
version = "0.72.0"
|
||||||
@@ -512,7 +492,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
name = "led_driver"
|
name = "led_driver"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.72.0",
|
"bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -543,7 +523,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"alsa",
|
"alsa",
|
||||||
"artnet_protocol",
|
"artnet_protocol",
|
||||||
"bindgen 0.71.1",
|
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
|||||||
@@ -7,3 +7,14 @@ edition = "2024"
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.72.0"
|
bindgen = "0.72.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["rpizero2"]
|
||||||
|
rpizero2 = ["rpi3"]
|
||||||
|
rpizero = ["rpi"]
|
||||||
|
rpi5 = []
|
||||||
|
rpi4 = []
|
||||||
|
rpi3 = []
|
||||||
|
rpi2 = []
|
||||||
|
rpi = []
|
||||||
|
16channel = []
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
use std::{env, path::PathBuf};
|
use std::{env, path::PathBuf};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo::rustc-link-search=/workspaces/LightSabre/lightsabre_backend/led_driver/lib");
|
println!(
|
||||||
|
"cargo::rustc-link-search=/workspaces/LightSabre/lightsabre_backend/led_driver/lib/bin"
|
||||||
|
);
|
||||||
|
|
||||||
// Tell cargo to tell rustc to link the RPiLedBars_drivers and logc libraries.
|
// Tell cargo to tell rustc to link the RPiLedBars_drivers and logc libraries.
|
||||||
|
#[cfg(not(feature = "16channel"))]
|
||||||
println!("cargo:rustc-link-lib=RpiLedBars_drivers_8ch");
|
println!("cargo:rustc-link-lib=RpiLedBars_drivers_8ch");
|
||||||
|
#[cfg(feature = "16channel")]
|
||||||
|
println!("cargo:rustc-link-lib=RpiLedBars_drivers_16ch");
|
||||||
println!("cargo:rustc-link-lib=logc");
|
println!("cargo:rustc-link-lib=logc");
|
||||||
|
|
||||||
// The bindgen::Builder is the main entry point to bindgen, and lets you build up options for the resulting bindings.
|
// The bindgen::Builder is the main entry point to bindgen, and lets you build up options for the resulting bindings.
|
||||||
|
|||||||
BIN
Binary file not shown.
Binary file not shown.
@@ -47,6 +47,12 @@ MEM_MAP vc_mem;
|
|||||||
TXDATA_T *txdata;
|
TXDATA_T *txdata;
|
||||||
TXDATA_T tx_buffer[TX_BUFF_LEN(CHAN_MAXLEDS)];
|
TXDATA_T tx_buffer[TX_BUFF_LEN(CHAN_MAXLEDS)];
|
||||||
|
|
||||||
|
#if LED_NCHANS <= 8
|
||||||
|
TXDATA_T tx_send_buffer[TX_BUFF_SIZE(CHAN_MAXLEDS)];
|
||||||
|
#else
|
||||||
|
TXDATA_T *tx_send_buffer = tx_buffer;
|
||||||
|
#endif /* LED_NCHANS <= 8 */
|
||||||
|
|
||||||
void swap_bytes();
|
void swap_bytes();
|
||||||
|
|
||||||
void leddriver_setup() {
|
void leddriver_setup() {
|
||||||
@@ -113,7 +119,7 @@ void leddriver_refresh() {
|
|||||||
usleep(10);
|
usleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(txdata, tx_buffer, TX_BUFF_SIZE(CHAN_MAXLEDS));
|
memcpy(txdata, tx_send_buffer, TX_BUFF_SIZE(CHAN_MAXLEDS));
|
||||||
enable_dma(DMA_CHAN_A);
|
enable_dma(DMA_CHAN_A);
|
||||||
start_smi(&vc_mem);
|
start_smi(&vc_mem);
|
||||||
usleep(10);
|
usleep(10);
|
||||||
@@ -122,11 +128,13 @@ void leddriver_refresh() {
|
|||||||
// Swap adjacent bytes in transmit data
|
// Swap adjacent bytes in transmit data
|
||||||
void swap_bytes() {
|
void swap_bytes() {
|
||||||
uint16_t *wp = (uint16_t *)tx_buffer;
|
uint16_t *wp = (uint16_t *)tx_buffer;
|
||||||
|
uint16_t *wp_dest = (uint16_t *)tx_send_buffer;
|
||||||
int len = TX_BUFF_SIZE(CHAN_MAXLEDS);
|
int len = TX_BUFF_SIZE(CHAN_MAXLEDS);
|
||||||
|
|
||||||
len = (len + 1) / 2;
|
len = (len + 1) / 2;
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
*wp = __builtin_bswap16(*wp);
|
*wp_dest = __builtin_bswap16(*wp);
|
||||||
|
wp_dest++;
|
||||||
wp++;
|
wp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
#include "include/log.h"
|
#include "include/log.h"
|
||||||
#include "src/leddriver/rpi_leddriver.h"
|
// #include "src/leddriver/rpi_leddriver.h"
|
||||||
#include "src/common.h"
|
#include "src/common.h"
|
||||||
|
#include "src/dma/rpi_dma.h"
|
||||||
|
#include "src/dma/rpi_videocore.h"
|
||||||
|
#include "src/smi/rpi_smi.h"
|
||||||
|
#include "src/gpio/rpi_gpio.h"
|
||||||
|
|
||||||
|
|
||||||
#define CHAN_MAXLEDS 60 // Maximum number of LEDs per channel
|
#define CHAN_MAXLEDS 60 // Maximum number of LEDs per channel
|
||||||
#define LED_NCHANS 8 // Number of LED channels (8 or 16)
|
|
||||||
|
|
||||||
#define TX_TEST 0 // If non-zero, use dummy Tx data
|
#define TX_TEST 0 // If non-zero, use dummy Tx data
|
||||||
#define LED_NBITS 24 // Number of data bits per LED
|
#define LED_NBITS 24 // Number of data bits per LED
|
||||||
@@ -11,8 +15,9 @@
|
|||||||
#define LED_POSTBITS 4 // Number of zero bits after LED data
|
#define LED_POSTBITS 4 // Number of zero bits after LED data
|
||||||
#define BIT_NPULSES 3 // Number of O/P pulses per LED bit
|
#define BIT_NPULSES 3 // Number of O/P pulses per LED bit
|
||||||
|
|
||||||
// Length of data for 1 row (1 LED on each channel)
|
// // Length of data for 1 row (1 LED on each channel)
|
||||||
#define LED_DLEN (LED_NBITS * BIT_NPULSES)
|
#define LED_DLEN (LED_NBITS * BIT_NPULSES)
|
||||||
|
#define LED_NCHANS 8 // Number of channels, 8 or 16
|
||||||
|
|
||||||
// Transmit data type, 8 or 16 bits
|
// Transmit data type, 8 or 16 bits
|
||||||
#if LED_NCHANS > 8
|
#if LED_NCHANS > 8
|
||||||
@@ -21,14 +26,19 @@ typedef uint16_t TXDATA_T;
|
|||||||
typedef uint8_t TXDATA_T;
|
typedef uint8_t TXDATA_T;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Ofset into Tx data buffer, given LED number in chan
|
|
||||||
|
// // Ofset into Tx data buffer, given LED number in chan
|
||||||
#define LED_TX_OSET(n) (LED_PREBITS + (LED_DLEN * (n)))
|
#define LED_TX_OSET(n) (LED_PREBITS + (LED_DLEN * (n)))
|
||||||
|
|
||||||
// Size of data buffers & NV memory, given number of LEDs per chan
|
// // Size of data buffers & NV memory, given number of LEDs per chan
|
||||||
#define TX_BUFF_LEN(n) (LED_TX_OSET(n) + LED_POSTBITS)
|
#define TX_BUFF_LEN(n) (LED_TX_OSET(n) + LED_POSTBITS)
|
||||||
#define TX_BUFF_SIZE(n) (TX_BUFF_LEN(n) * sizeof(TXDATA_T))
|
#define TX_BUFF_SIZE(n) (TX_BUFF_LEN(n) * sizeof(TXDATA_T))
|
||||||
|
|
||||||
|
#define PAGE_SIZE 0x1000
|
||||||
#define VC_MEM_SIZE (PAGE_SIZE + TX_BUFF_SIZE(CHAN_MAXLEDS))
|
#define VC_MEM_SIZE (PAGE_SIZE + TX_BUFF_SIZE(CHAN_MAXLEDS))
|
||||||
|
|
||||||
extern TXDATA_T tx_buffer[TX_BUFF_LEN(CHAN_MAXLEDS)];
|
|
||||||
|
// extern TXDATA_T tx_buffer[TX_BUFF_LEN(CHAN_MAXLEDS)];
|
||||||
|
extern TXDATA_T tx_send_buffer[TX_BUFF_LEN(CHAN_MAXLEDS)];
|
||||||
extern TXDATA_T *txdata;
|
extern TXDATA_T *txdata;
|
||||||
extern MEM_MAP vc_mem;
|
extern MEM_MAP vc_mem;
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
pub const LED_NCHANS: usize = 16_usize; // Number of channels (strips)
|
||||||
|
pub const CHAN_NUM_MASK: u8 = 0b1111_u8; // Mask to get channel number from port address
|
||||||
|
|
||||||
|
pub type TX_DATA_T = u16; // Type of Tx data buffer
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
pub const LED_NCHANS: usize = 8_usize; // Number of channels (strips)
|
||||||
|
pub const CHAN_NUM_MASK: u8 = 0b0111_u8; // Mask to get channel number from port address
|
||||||
|
|
||||||
|
pub type TX_DATA_T = u8; // Type of Tx data buffer
|
||||||
@@ -5,34 +5,110 @@
|
|||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||||
|
|
||||||
pub struct LedDriver {
|
#[cfg_attr(not(feature = "16channel"), path = "channel_8.rs")]
|
||||||
led_per_strip_count: usize,
|
#[cfg_attr(feature = "16channel", path = "channel_16.rs")]
|
||||||
strip_count: usize,
|
pub mod channel;
|
||||||
}
|
|
||||||
|
pub use channel::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "rpi")]
|
||||||
|
/// Location of peripheral registers in physical memory for RaspberryPi 1 and Zero
|
||||||
|
/// This is the base address for the BCM2835 SoC peripherals
|
||||||
|
const PHYS_REG_BASE: usize = 0x20000000;
|
||||||
|
#[cfg(any(feature = "rpi2", feature = "rpi3"))]
|
||||||
|
/// Location of peripheral registers in physical memory for RaspberryPi 2, 3 and Zero2
|
||||||
|
/// This is the base address for the BCM2836/BCM2837 SoC peripherals
|
||||||
|
const PHYS_REG_BASE: usize = 0x3F000000;
|
||||||
|
#[cfg(any(feature = "rpi4", feature = "rpi5"))]
|
||||||
|
// Location of peripheral registers in physical memory for RaspberryPi 4 and 5
|
||||||
|
/// This is the base address for the BCM2711/BCM2712 SoC peripherals
|
||||||
|
const PHYS_REG_BASE: usize = 0xFE000000;
|
||||||
|
|
||||||
|
#[cfg(feature = "rpi")]
|
||||||
|
/// Clock frequency for RaspberryPi 1 and Zero
|
||||||
|
const CLOCK_SPEED: usize = 400000000;
|
||||||
|
#[cfg(any(feature = "rpi2", feature = "rpi3", feature = "rpi4", feature = "rpi5"))]
|
||||||
|
/// Clock frequency for RaspberryPi 2, 3, Zero2 and 4 and 5
|
||||||
|
const CLOCK_SPEED: usize = 250000000;
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "rpi4", feature = "rpi5")))] // Timings for RPi v0-3 (1 GHz)
|
||||||
|
const SMI_TIMING: [std::os::raw::c_int; 4] = [10, 10, 20, 10]; // 400 ns cycle time
|
||||||
|
#[cfg(any(feature = "rpi4", feature = "rpi5"))] // Timings for RPi v4 (1.5 GHz)
|
||||||
|
const SMI_TIMING: [std::os::raw::c_int; 4] = [10, 15, 30, 15]; // 400 ns cycle time
|
||||||
|
|
||||||
// Offset into Tx data buffer, given LED number in chan
|
// Offset into Tx data buffer, given LED number in chan
|
||||||
macro_rules! LED_TX_OSET {
|
macro_rules! LED_TX_OFFSET {
|
||||||
($n:expr) => {
|
($n:expr) => {
|
||||||
LED_PREBITS + (LED_DLEN * $n)
|
LedDriver::LED_PREBITS + (LedDriver::LED_DLEN * $n)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! TX_BUFF_LEN {
|
||||||
|
($n:expr) => {
|
||||||
|
LED_TX_OFFSET!($n) + LedDriver::LED_POSTBITS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! TX_BUFF_SIZE {
|
||||||
|
($n:expr) => {
|
||||||
|
TX_BUFF_LEN!($n) * std::mem::size_of::<TX_DATA_T>()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LedDriver {
|
||||||
|
led_per_strip_count: usize,
|
||||||
|
strip_count: usize,
|
||||||
|
tx_buffer: [TX_DATA_T; TX_BUFF_LEN!(Self::CHAN_MAXLEDS)],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for LedDriver {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LedDriver {
|
impl LedDriver {
|
||||||
const LED_NCHANS: usize = LED_NCHANS as usize; // Number of channels (strips)
|
pub const CHAN_MAXLEDS: usize = 60; // Maximum number of LEDs per channel
|
||||||
const TX_TEST: usize = TX_TEST as usize; // If non-zero, use dummy Tx data
|
|
||||||
const LED_NBITS: usize = LED_NBITS as usize; // Number of data bits per LED
|
const TX_TEST: usize = 0; // If non-zero, use dummy Tx data
|
||||||
pub const LED_PREBITS: usize = LED_PREBITS as usize; // Number of zero bits before LED data
|
const LED_NBITS: usize = 24; // Number of data bits per LED
|
||||||
const LED_POSTBITS: usize = LED_POSTBITS as usize; // Number of zero bits after LED data
|
pub const LED_PREBITS: usize = 4; // Number of zero bits before LED data
|
||||||
const BIT_NPULSES: usize = BIT_NPULSES as usize; // Number of O/P pulses per LED bit
|
pub const LED_POSTBITS: usize = 4; // Number of zero bits after LED data
|
||||||
|
const BIT_NPULSES: usize = 3; // Number of O/P pulses per LED bit
|
||||||
|
|
||||||
|
pub const PAGE_SIZE: usize = 0x1000;
|
||||||
|
pub const VC_MEM_SIZE: usize = Self::PAGE_SIZE + TX_BUFF_SIZE!(Self::CHAN_MAXLEDS);
|
||||||
|
|
||||||
// Length of data for 1 row (1 LED on each channel)
|
// Length of data for 1 row (1 LED on each channel)
|
||||||
pub const LED_DLEN: usize = Self::LED_NBITS * Self::BIT_NPULSES;
|
pub const LED_DLEN: usize = Self::LED_NBITS * Self::BIT_NPULSES;
|
||||||
|
|
||||||
pub fn new(led_per_strip_count: usize, strip_count: usize) -> LedDriver {
|
pub fn new(led_per_strip_count: usize, strip_count: usize) -> LedDriver {
|
||||||
unsafe { leddriver_setup() };
|
unsafe {
|
||||||
|
videocore_setup(&raw mut vc_mem, Self::VC_MEM_SIZE as i32);
|
||||||
|
gpio_setup();
|
||||||
|
smi_setup(
|
||||||
|
channel::LED_NCHANS as i32,
|
||||||
|
SMI_TIMING[0],
|
||||||
|
SMI_TIMING[1],
|
||||||
|
SMI_TIMING[2],
|
||||||
|
SMI_TIMING[3],
|
||||||
|
&raw mut vc_mem,
|
||||||
|
TX_BUFF_LEN!(Self::CHAN_MAXLEDS) as i32,
|
||||||
|
&raw mut txdata,
|
||||||
|
);
|
||||||
|
}
|
||||||
LedDriver {
|
LedDriver {
|
||||||
led_per_strip_count,
|
led_per_strip_count,
|
||||||
strip_count,
|
strip_count,
|
||||||
|
tx_buffer: [0; TX_BUFF_LEN!(Self::CHAN_MAXLEDS)],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
videocore_close(&raw mut vc_mem);
|
||||||
|
smi_close(channel::LED_NCHANS as i32);
|
||||||
|
gpio_close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,11 +120,7 @@ impl LedDriver {
|
|||||||
self.strip_count
|
self.strip_count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_color(&self, rgb: u32, index: usize) {
|
pub fn set_color_till_led(&mut self, color: u32, led_num: usize) {
|
||||||
unsafe { set_color(rgb, index as i32) };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_color_till_led(&self, color: u32, led_num: usize) {
|
|
||||||
let led_num = led_num.min(self.get_led_per_strip_count());
|
let led_num = led_num.min(self.get_led_per_strip_count());
|
||||||
// Set color for all strips
|
// Set color for all strips
|
||||||
for led_index in 0..=led_num {
|
for led_index in 0..=led_num {
|
||||||
@@ -59,13 +131,15 @@ impl LedDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn direct_set_color(&self, rgb: u32, index: usize) {
|
pub fn direct_set_color(&mut self, rgb: u32, index: usize) {
|
||||||
let mut mask = 0_u32;
|
let mut mask = 0_u32;
|
||||||
let mut offset = LED_TX_OSET!(index as u32) as usize;
|
let mut offset = LED_TX_OFFSET!(index);
|
||||||
|
|
||||||
// For each bit of the 24-bit RGB values..
|
// For each bit of the 24-bit RGB values..
|
||||||
for n in 0..Self::LED_NBITS {
|
for n in 0..Self::LED_NBITS {
|
||||||
let tx_data = unsafe { &mut tx_buffer[offset..offset + Self::BIT_NPULSES] };
|
let tx_data = &mut self.tx_buffer[offset..offset + Self::BIT_NPULSES];
|
||||||
|
// let tx_data =
|
||||||
|
// unsafe { std::slice::from_raw_parts_mut(tx_buffer.add(offset), Self::BIT_NPULSES) };
|
||||||
// Mask to convert RGB to GRB, M.S bit first
|
// Mask to convert RGB to GRB, M.S bit first
|
||||||
Self::compute_mask(&mut mask, n);
|
Self::compute_mask(&mut mask, n);
|
||||||
|
|
||||||
@@ -79,14 +153,17 @@ impl LedDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_led_color(&self, rgb: u32, led_index: usize, strip_index: usize) {
|
pub fn set_led_color(&mut self, rgb: u32, led_index: usize, strip_index: usize) {
|
||||||
let mut mask = 0_u32;
|
let mut mask = 0_u32;
|
||||||
let mut offset = LED_TX_OSET!(led_index as u32) as usize;
|
let mut offset = LED_TX_OFFSET!(led_index);
|
||||||
let strip_mask = !(0b1_u8 << strip_index); // Mask to clear the led bit of desired strip
|
let strip_mask = !(0b1 << strip_index); // Mask to clear the led bit of desired strip
|
||||||
|
|
||||||
// For each bit of the 24-bit RGB values..
|
// For each bit of the 24-bit RGB values..
|
||||||
for n in 0..Self::LED_NBITS {
|
for n in 0..Self::LED_NBITS {
|
||||||
let tx_data = unsafe { &mut tx_buffer[offset..offset + Self::BIT_NPULSES] };
|
// let tx_data = unsafe { &mut *tx_buffer[offset..offset + Self::BIT_NPULSES] };
|
||||||
|
// let tx_data =
|
||||||
|
// unsafe { std::slice::from_raw_parts_mut(tx_buffer.add(offset), Self::BIT_NPULSES) };
|
||||||
|
let tx_data = &mut self.tx_buffer[offset..offset + Self::BIT_NPULSES];
|
||||||
// Mask to convert RGB to GRB, M.S bit first
|
// Mask to convert RGB to GRB, M.S bit first
|
||||||
Self::compute_mask(&mut mask, n);
|
Self::compute_mask(&mut mask, n);
|
||||||
|
|
||||||
@@ -105,13 +182,17 @@ impl LedDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_strip_index_colors(&self, rgb: [u32; Self::LED_NCHANS], led_index: usize) {
|
pub fn set_strip_index_colors(&mut self, rgb: [u32; channel::LED_NCHANS], led_index: usize) {
|
||||||
let mut mask = 0_u32;
|
let mut mask = 0_u32;
|
||||||
let mut offset = LED_TX_OSET!(led_index as u32) as usize;
|
let mut offset = LED_TX_OFFSET!(led_index);
|
||||||
|
|
||||||
// For each bit of the 24-bit RGB values..
|
// For each bit of the 24-bit RGB values..
|
||||||
for n in 0..Self::LED_NBITS {
|
for n in 0..Self::LED_NBITS {
|
||||||
let tx_data = unsafe { &mut tx_buffer[offset..offset + Self::BIT_NPULSES] };
|
// let tx_data = unsafe { &mut tx_buffer[offset..offset + Self::BIT_NPULSES] };
|
||||||
|
// let tx_data =
|
||||||
|
// unsafe { std::slice::from_raw_parts_mut(tx_buffer.add(offset), Self::BIT_NPULSES) };
|
||||||
|
let tx_data = &mut self.tx_buffer[offset..offset + Self::BIT_NPULSES];
|
||||||
|
|
||||||
// Mask to convert RGB to GRB, M.S bit first
|
// Mask to convert RGB to GRB, M.S bit first
|
||||||
Self::compute_mask(&mut mask, n);
|
Self::compute_mask(&mut mask, n);
|
||||||
|
|
||||||
@@ -131,8 +212,32 @@ impl LedDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh(&self) {
|
// pub fn refresh(&self) {
|
||||||
unsafe { leddriver_refresh() };
|
// unsafe { leddriver_refresh() };
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn direct_refresh(&mut self) {
|
||||||
|
// #[cfg(not(feature = "16channel"))]
|
||||||
|
// self.swap_bytes();
|
||||||
|
#[cfg(not(feature = "16channel"))]
|
||||||
|
let send_buffer = self.safe_swap_bytes();
|
||||||
|
#[cfg(feature = "16channel")]
|
||||||
|
let send_buffer = self.tx_buffer;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
while dma_active(DMA_CHAN_A as i32) != 0 {
|
||||||
|
std::thread::sleep(std::time::Duration::from_micros(10));
|
||||||
|
}
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
|
std::ptr::copy_nonoverlapping(
|
||||||
|
send_buffer.as_ptr(),
|
||||||
|
txdata,
|
||||||
|
TX_BUFF_LEN!(Self::CHAN_MAXLEDS),
|
||||||
|
);
|
||||||
|
enable_dma(DMA_CHAN_A as i32);
|
||||||
|
start_smi(&raw mut vc_mem);
|
||||||
|
std::thread::sleep(std::time::Duration::from_micros(10));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn color_hsv(&self, hue: u16, sat: u8, val: u8) -> u32 {
|
// pub fn color_hsv(&self, hue: u16, sat: u8, val: u8) -> u32 {
|
||||||
@@ -150,10 +255,58 @@ impl LedDriver {
|
|||||||
*mask >> 1
|
*mask >> 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "16channel"))]
|
||||||
|
fn safe_swap_bytes(&self) -> [TX_DATA_T; TX_BUFF_SIZE!(Self::CHAN_MAXLEDS)] {
|
||||||
|
self.tx_buffer
|
||||||
|
.chunks(2)
|
||||||
|
.map(|chunk| {
|
||||||
|
if chunk.len() == 2 {
|
||||||
|
[chunk[1], chunk[0]]
|
||||||
|
} else {
|
||||||
|
[0, chunk[0]]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or_else(|o: Vec<_>| {
|
||||||
|
panic!(
|
||||||
|
"Failed to convert Vec of length {} to array of size {}",
|
||||||
|
o.len(),
|
||||||
|
TX_BUFF_SIZE!(Self::CHAN_MAXLEDS)
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for LedDriver {
|
#[cfg(not(feature = "16channel"))]
|
||||||
fn drop(&mut self) {
|
fn swap_bytes(&mut self) {
|
||||||
unsafe { leddriver_close() };
|
/*
|
||||||
|
uint16_t *wp = (uint16_t *)tx_buffer;
|
||||||
|
int len = TX_BUFF_SIZE(CHAN_MAXLEDS);
|
||||||
|
|
||||||
|
len = (len + 1) / 2;
|
||||||
|
while (len-- > 0) {
|
||||||
|
*wp = __builtin_bswap16(*wp);
|
||||||
|
wp++;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
unsafe {
|
||||||
|
for (i, chunk) in self.tx_buffer.chunks(2).enumerate() {
|
||||||
|
if chunk.len() == 2 {
|
||||||
|
tx_send_buffer[i * 2] = chunk[1];
|
||||||
|
// *tx_send_buffer.add(i * 2) = chunk[1];
|
||||||
|
tx_send_buffer[i * 2 + 1] = chunk[0];
|
||||||
|
// *tx_send_buffer.add(i * 2 + 1) = chunk[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// unsafe {
|
||||||
|
// let wp = self.tx_buffer as *mut u16;
|
||||||
|
// let len = (TX_BUFF_SIZE!(Self::CHAN_MAXLEDS) + 1) / 2;
|
||||||
|
// for i in 0..len {
|
||||||
|
// let p = wp.add(i);
|
||||||
|
// *p = (*p).swap_bytes();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,3 @@ rppal = "0.22.1"
|
|||||||
spectrum-analyzer = "1.7.0"
|
spectrum-analyzer = "1.7.0"
|
||||||
textplots = "0.8.7"
|
textplots = "0.8.7"
|
||||||
led_driver = { path = "../led_driver" }
|
led_driver = { path = "../led_driver" }
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
bindgen = "0.71.0"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["rpizero2", "16channel"]
|
|
||||||
rpizero2 = ["rpi3"]
|
|
||||||
rpizero = ["rpi"]
|
|
||||||
rpi4 = []
|
|
||||||
rpi3 = []
|
|
||||||
rpi2 = []
|
|
||||||
rpi = []
|
|
||||||
16channel = []
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -110,8 +110,10 @@ impl AppModeHandler for ArtNetMode {
|
|||||||
is_first_data_frame = false;
|
is_first_data_frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let led_strip = (u16::from(output.port_address) & 0b0111_u16) as usize;
|
let led_strip = (u16::from(output.port_address)
|
||||||
//output.port_address
|
& led_driver::CHAN_NUM_MASK as u16)
|
||||||
|
as usize;
|
||||||
|
|
||||||
for i in 0..led_driver.get_led_per_strip_count() {
|
for i in 0..led_driver.get_led_per_strip_count() {
|
||||||
let data_index = i * 3;
|
let data_index = i * 3;
|
||||||
let g = *output.data.as_ref().get(data_index).unwrap_or(&0);
|
let g = *output.data.as_ref().get(data_index).unwrap_or(&0);
|
||||||
@@ -120,9 +122,9 @@ impl AppModeHandler for ArtNetMode {
|
|||||||
// let color = (r as u32) << 16 + (g as u32) << 8 + b;
|
// let color = (r as u32) << 16 + (g as u32) << 8 + b;
|
||||||
let color: u32 =
|
let color: u32 =
|
||||||
((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
|
((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
|
||||||
led_driver.direct_set_color(color, i);
|
led_driver.set_led_color(color, i, led_strip);
|
||||||
}
|
}
|
||||||
led_driver.refresh();
|
led_driver.direct_refresh();
|
||||||
}
|
}
|
||||||
ArtCommand::PollReply(_) => {
|
ArtCommand::PollReply(_) => {
|
||||||
log::trace!("[ArtNet] Received PollReply command, ignoring");
|
log::trace!("[ArtNet] Received PollReply command, ignoring");
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ impl AppModeHandler for DiagnosticsMode {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
log::trace!("Setting LED {} to color {:06x}", led, color);
|
log::trace!("Setting LED {} to color {:06x}", led, color);
|
||||||
led_driver.refresh();
|
led_driver.direct_refresh();
|
||||||
}
|
}
|
||||||
self.cycle_count += 1;
|
self.cycle_count += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ impl AppModeHandler for StandaloneMode {
|
|||||||
// Set the remaining LEDs to black
|
// Set the remaining LEDs to black
|
||||||
led_driver.direct_set_color(0x000000, i);
|
led_driver.direct_set_color(0x000000, i);
|
||||||
}
|
}
|
||||||
led_driver.refresh();
|
led_driver.direct_refresh();
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::trace!("[Standalone] No audio data received");
|
log::trace!("[Standalone] No audio data received");
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
mod channels;
|
mod channels;
|
||||||
mod config;
|
|
||||||
mod cputasks;
|
mod cputasks;
|
||||||
mod devices;
|
mod devices;
|
||||||
mod iotasks;
|
mod iotasks;
|
||||||
@@ -107,7 +106,10 @@ impl From<LightSabre> for LightSabreIntitialized {
|
|||||||
impl From<LightSabreIntitialized> for LightSabreRunning {
|
impl From<LightSabreIntitialized> for LightSabreRunning {
|
||||||
fn from(mut value: LightSabreIntitialized) -> Self {
|
fn from(mut value: LightSabreIntitialized) -> Self {
|
||||||
LightSabreRunning {
|
LightSabreRunning {
|
||||||
join_handle: std::thread::spawn(move || run(&mut value.ctx)),
|
join_handle: std::thread::Builder::new()
|
||||||
|
.name("main_app".to_string())
|
||||||
|
.spawn(move || run(&mut value.ctx))
|
||||||
|
.expect("Failed to start main app thread"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user