neopixel: Improve timing of gpio bit-banging
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
0af5b9ff6d
commit
d5cc2a7b7b
|
@ -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=%u", cq=cmd_queue)
|
"neopixel_send oid=%c data=%*s", 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, val], minclock=minclock)
|
self.neopixel_send_cmd.send([self.oid, [green, red, blue]],
|
||||||
|
minclock=minclock)
|
||||||
|
|
||||||
def load_config_prefix(config):
|
def load_config_prefix(config):
|
||||||
return PrinterNeoPixel(config)
|
return PrinterNeoPixel(config)
|
||||||
|
|
|
@ -35,7 +35,7 @@ timer_from_ns(uint32_t ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
send_data(struct neopixel_s *n, uint32_t data)
|
send_data(struct neopixel_s *n, uint8_t *data, uint_fast8_t data_len)
|
||||||
{
|
{
|
||||||
// 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();
|
||||||
|
@ -45,45 +45,48 @@ send_data(struct neopixel_s *n, uint32_t data)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gpio_out pin = n->pin;
|
struct gpio_out pin = n->pin;
|
||||||
uint32_t expire_time = cur + 0x40000000;
|
uint32_t min_wait_time = cur, max_wait_time = cur + 0x40000000;
|
||||||
uint_fast8_t bits = 24;
|
while (data_len--) {
|
||||||
|
uint_fast8_t byte = *data++;
|
||||||
|
uint_fast8_t bits = 8;
|
||||||
while (bits--) {
|
while (bits--) {
|
||||||
// Calculate pulse duration
|
// Calculate pulse duration
|
||||||
uint32_t on, off;
|
uint32_t on, off;
|
||||||
if (data & 0x800000) {
|
if (byte & 0x80) {
|
||||||
on = timer_from_ns(700 - 150);
|
on = timer_from_ns(700 - 150);
|
||||||
off = timer_from_ns(600 - 150);
|
off = timer_from_ns(600 - 150);
|
||||||
} else {
|
} else {
|
||||||
on = timer_from_ns(350 - 150);
|
on = timer_from_ns(350 - 150);
|
||||||
off = timer_from_ns(800 - 150);
|
off = timer_from_ns(800 - 150);
|
||||||
}
|
}
|
||||||
data <<= 1;
|
byte <<= 1;
|
||||||
|
|
||||||
// Set output high
|
// Set output high
|
||||||
|
do {
|
||||||
|
irq_poll();
|
||||||
|
cur = timer_read_time();
|
||||||
|
} while (timer_is_before(cur, min_wait_time));
|
||||||
gpio_out_write(pin, 1);
|
gpio_out_write(pin, 1);
|
||||||
uint32_t on_start_time = timer_read_time();
|
uint32_t on_start_time = timer_read_time();
|
||||||
if (timer_is_before(expire_time, on_start_time))
|
if (timer_is_before(max_wait_time, on_start_time))
|
||||||
goto fail;
|
goto fail;
|
||||||
cur = on_start_time;
|
min_wait_time = on_start_time + on;
|
||||||
while (timer_is_before(cur, on_start_time + on)) {
|
max_wait_time = cur + on + timer_from_ns(300);
|
||||||
irq_poll();
|
|
||||||
cur = timer_read_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set output low
|
// Set output low
|
||||||
gpio_out_write(pin, 0);
|
do {
|
||||||
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();
|
irq_poll();
|
||||||
cur = timer_read_time();
|
cur = timer_read_time();
|
||||||
|
} while (timer_is_before(cur, min_wait_time));
|
||||||
|
gpio_out_write(pin, 0);
|
||||||
|
uint32_t off_start_time = timer_read_time();
|
||||||
|
if (timer_is_before(max_wait_time, off_start_time))
|
||||||
|
goto fail;
|
||||||
|
min_wait_time = off_start_time + off;
|
||||||
|
max_wait_time = cur + off + timer_from_ns(300);
|
||||||
}
|
}
|
||||||
expire_time = off_start_time + off + timer_from_ns(300);
|
|
||||||
}
|
}
|
||||||
n->last_req_time = cur;
|
n->last_req_time = timer_read_time();
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
// A hardware irq messed up the transmission - report a failure
|
// A hardware irq messed up the transmission - report a failure
|
||||||
|
@ -97,15 +100,16 @@ 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);
|
||||||
uint32_t data = args[1];
|
uint_fast8_t data_len = 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);
|
int ret = send_data(n, data, data_len);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if !CONFIG_MACH_AVR
|
#if !CONFIG_MACH_AVR
|
||||||
DECL_COMMAND(command_neopixel_send, "neopixel_send oid=%c data=%u");
|
DECL_COMMAND(command_neopixel_send, "neopixel_send oid=%c data=%*s");
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue