neopixel: Optimize the update loop

Optimize the transmit code so it can run on some slower ARM cpus.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2019-07-12 23:39:00 -04:00
parent b7bc96c3b2
commit be2d0abbab
2 changed files with 42 additions and 46 deletions

View File

@ -25,7 +25,7 @@ class PrinterNeoPixel:
def build_config(self): def build_config(self):
cmd_queue = self.mcu.alloc_command_queue() cmd_queue = self.mcu.alloc_command_queue()
self.neopixel_send_cmd = self.mcu.lookup_command( self.neopixel_send_cmd = self.mcu.lookup_command(
"neopixel_send oid=%c data=%*s", cq=cmd_queue) "neopixel_send oid=%c data=%u", cq=cmd_queue)
cmd_SET_NEOPIXEL_help = "Set the color of a neopixel led" cmd_SET_NEOPIXEL_help = "Set the color of a neopixel led"
def cmd_SET_NEOPIXEL(self, params): def cmd_SET_NEOPIXEL(self, params):
# Parse parameters # Parse parameters
@ -35,11 +35,11 @@ class PrinterNeoPixel:
red = int(red * 255. + .5) red = int(red * 255. + .5)
blue = int(blue * 255. + .5) blue = int(blue * 255. + .5)
green = int(green * 255. + .5) green = int(green * 255. + .5)
val = (green << 16) | (red << 8) | blue
# Send command # Send command
print_time = self.printer.lookup_object('toolhead').get_last_move_time() print_time = self.printer.lookup_object('toolhead').get_last_move_time()
minclock = self.mcu.print_time_to_clock(print_time) minclock = self.mcu.print_time_to_clock(print_time)
self.neopixel_send_cmd.send([self.oid, [green, red, blue]], self.neopixel_send_cmd.send([self.oid, val], minclock=minclock)
minclock=minclock)
def load_config_prefix(config): def load_config_prefix(config):
return PrinterNeoPixel(config) return PrinterNeoPixel(config)

View File

@ -35,7 +35,7 @@ timer_from_ns(uint32_t ns)
} }
static int static int
send_data(struct neopixel_s *n, uint8_t *data, uint_fast8_t data_len) send_data(struct neopixel_s *n, uint32_t data)
{ {
// Make sure at least 50us has passed since last request // Make sure at least 50us has passed since last request
uint32_t last_req_time = n->last_req_time, cur = timer_read_time(); uint32_t last_req_time = n->last_req_time, cur = timer_read_time();
@ -46,45 +46,42 @@ send_data(struct neopixel_s *n, uint8_t *data, uint_fast8_t data_len)
struct gpio_out pin = n->pin; struct gpio_out pin = n->pin;
uint32_t expire_time = cur + 0x40000000; uint32_t expire_time = cur + 0x40000000;
while (data_len--) { uint_fast8_t bits = 24;
uint_fast8_t byte = *data++; while (bits--) {
uint_fast8_t bits = 8; // Calculate pulse duration
while (bits--) { uint32_t on, off;
// Calculate pulse duration if (data & 0x800000) {
uint32_t on, off; on = timer_from_ns(700 - 150);
if (byte & 0x80) { off = timer_from_ns(600 - 150);
on = timer_from_ns(700 - 150); } else {
off = timer_from_ns(600 - 150); on = timer_from_ns(350 - 150);
} else { off = timer_from_ns(800 - 150);
on = timer_from_ns(350 - 150);
off = timer_from_ns(800 - 150);
}
byte <<= 1;
// Set output high
gpio_out_toggle(pin);
uint32_t on_start_time = timer_read_time();
if (timer_is_before(expire_time, on_start_time))
goto fail;
cur = on_start_time;
while (timer_is_before(cur, on_start_time + on)) {
irq_poll();
cur = timer_read_time();
}
// Set output low
gpio_out_toggle(pin);
uint32_t off_start_time = timer_read_time();
expire_time = on_start_time + on + timer_from_ns(300);
if (timer_is_before(expire_time, off_start_time))
goto fail;
cur = off_start_time;
while (timer_is_before(cur, off_start_time + off)) {
irq_poll();
cur = timer_read_time();
}
expire_time = off_start_time + off + timer_from_ns(300);
} }
data <<= 1;
// Set output high
gpio_out_write(pin, 1);
uint32_t on_start_time = timer_read_time();
if (timer_is_before(expire_time, on_start_time))
goto fail;
cur = on_start_time;
while (timer_is_before(cur, on_start_time + on)) {
irq_poll();
cur = timer_read_time();
}
// Set output low
gpio_out_write(pin, 0);
uint32_t off_start_time = timer_read_time();
expire_time = on_start_time + on + timer_from_ns(300);
if (timer_is_before(expire_time, off_start_time))
goto fail;
cur = off_start_time;
while (timer_is_before(cur, off_start_time + off)) {
irq_poll();
cur = timer_read_time();
}
expire_time = off_start_time + off + timer_from_ns(300);
} }
n->last_req_time = cur; n->last_req_time = cur;
return 0; return 0;
@ -99,16 +96,15 @@ command_neopixel_send(uint32_t *args)
{ {
uint8_t oid = args[0]; uint8_t oid = args[0];
struct neopixel_s *n = oid_lookup(oid, command_config_neopixel); struct neopixel_s *n = oid_lookup(oid, command_config_neopixel);
uint_fast8_t data_len = args[1]; uint32_t data = args[1];
uint8_t *data = (void*)(size_t)args[2];
uint_fast8_t retry = 8; uint_fast8_t retry = 8;
while (retry--) { while (retry--) {
int ret = send_data(n, data, data_len); int ret = send_data(n, data);
if (!ret) if (!ret)
break; break;
} }
} }
#if !CONFIG_MACH_AVR #if !CONFIG_MACH_AVR
DECL_COMMAND(command_neopixel_send, "neopixel_send oid=%c data=%*s"); DECL_COMMAND(command_neopixel_send, "neopixel_send oid=%c data=%u");
#endif #endif