Skip to content

Commit

Permalink
Updated to support new MPG mode. Updated for core signature change.
Browse files Browse the repository at this point in the history
Enhanced Neopixel support. Note: Not yet used by any boards.
  • Loading branch information
terjeio committed Feb 5, 2024
1 parent 49f2e4d commit fdd4ad2
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 64 deletions.
161 changes: 110 additions & 51 deletions main/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@
Copyright (c) 2011-2015 Sungeun K. Jeon
Copyright (c) 2009-2011 Simen Svale Skogsrud
Grbl is free software: you can redistribute it and/or modify
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Grbl is distributed in the hope that it will be useful,
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdint.h>
Expand Down Expand Up @@ -424,6 +424,10 @@ static probe_state_t probe = {
static ioexpand_t iopins = {0};
#endif

#ifdef NEOPIXELS_PIN
neopixel_cfg_t neopixel = { .intensity = 255 };
#endif

#if I2C_STROBE_ENABLE

static driver_irq_handler_t i2c_strobe = { .type = IRQ_I2C_Strobe };
Expand Down Expand Up @@ -1919,7 +1923,7 @@ static void modeChange (void *data)
stream_mpg_enable(!DIGITAL_IN(MPG_ENABLE_PIN));
}

static void modeEnable (void *data)
static void mpg_enable (void *data)
{
if(sys.mpg_mode == DIGITAL_IN(MPG_ENABLE_PIN))
stream_mpg_enable(true);
Expand Down Expand Up @@ -1992,6 +1996,31 @@ static void settings_changed (settings_t *settings, settings_changed_flags_t cha
{
if(IOInitDone) {

#ifdef NEOPIXELS_PIN

if(neopixel.leds == NULL || hal.rgb.num_devices != settings->rgb_strip0_length) {

if(settings->rgb_strip0_length == 0)
settings->rgb_strip0_length = hal.rgb.num_devices;
else
hal.rgb.num_devices = settings->rgb_strip0_length;

if(neopixel.leds) {
free(neopixel.leds);
neopixel.leds = NULL;
}

if(hal.rgb.num_devices) {
neopixel.num_bytes = hal.rgb.num_devices * 3;
if((neopixel.leds = calloc(neopixel.num_bytes, sizeof(uint8_t))) == NULL)
hal.rgb.num_devices = 0;
}

neopixel.num_leds = hal.rgb.num_devices;
}

#endif

#if DRIVER_SPINDLE_PWM_ENABLE
if(changed.spindle) {
spindleConfig(spindle_get_hal(spindle_id, SpindleHAL_Configured));
Expand Down Expand Up @@ -2396,7 +2425,11 @@ static char *sdcard_mount (FATFS **fs)
#define NEOPIXELS_NUM 1
#endif

static rmt_config_t neo_config = RMT_DEFAULT_CONFIG_TX(NEOPIXELS_PIN, 3); // TODO: sort out channel allocation
#if CONFIG_IDF_TARGET_ESP32S3
static rmt_config_t neo_config = RMT_DEFAULT_CONFIG_TX(NEOPIXELS_PIN, 3);
#else
static rmt_config_t neo_config = RMT_DEFAULT_CONFIG_TX(NEOPIXELS_PIN, 7);
#endif

#define WS2812_T0H_NS (450)
#define WS2812_T0L_NS (850)
Expand All @@ -2414,65 +2447,74 @@ static rmt_config_t neo_config = RMT_DEFAULT_CONFIG_TX(NEOPIXELS_PIN, 3); // TOD
#define WS2812_T1L_NS (1300)
*/

static uint8_t pixels[NEOPIXELS_NUM * 3] = {0};
static uint32_t t0h_ticks = 0, t1h_ticks = 0, t0l_ticks = 0, t1l_ticks = 0;

static void IRAM_ATTR ws2812_rmt_adapter (const void *src, rmt_item32_t *dest, size_t src_size,
size_t wanted_num, size_t *translated_size, size_t *item_num)
{
if (src == NULL || dest == NULL) {
*translated_size = 0;
*item_num = 0;
return;
}
const rmt_item32_t bit0 = {{{ t0h_ticks, 1, t0l_ticks, 0 }}}; //Logical 0
const rmt_item32_t bit1 = {{{ t1h_ticks, 1, t1l_ticks, 0 }}}; //Logical 1
size_t size = 0;
size_t num = 0;
uint8_t *psrc = (uint8_t *)src;
rmt_item32_t *pdest = dest;
while (size < src_size && num < wanted_num) {
for (int i = 0; i < 8; i++) {
// MSB first
if (*psrc & (1 << (7 - i))) {
pdest->val = bit1.val;
} else {
pdest->val = bit0.val;
}
num++;
pdest++;

rgb_color_t color = {0};
size_t size = 0, num = 0;
uint8_t *psrc = (uint8_t *)src, bitmask;

if(!(src == NULL || dest == NULL)) {
while(size < src_size && num < wanted_num) {

color.G = *psrc++;
color.R = *psrc++;
color.B = *psrc++;
color = rgb_set_intensity(color, neopixel.intensity);

bitmask = 0b10000000;
do {
dest->val = color.G & bitmask ? bit1.val : bit0.val;
dest++;
} while(bitmask >>= 1);

bitmask = 0b10000000;
do {
dest->val = color.R & bitmask ? bit1.val : bit0.val;
dest++;
} while(bitmask >>= 1);

bitmask = 0b10000000;
do {
dest->val = color.B & bitmask ? bit1.val : bit0.val;
dest++;
} while(bitmask >>= 1);

num += 24;
size += 3;
}
size++;
psrc++;
}

*translated_size = size;
*item_num = num;
}

void neopixels_write (void)
{
rmt_write_sample(neo_config.channel, pixels, sizeof(pixels), true);
uint8_t *buf = neopixel.leds;
size_t size = neopixel.num_bytes;

if(buf) do {
rmt_write_sample(neo_config.channel, buf, size > 6 ? 6 : size, true);
buf += size > 6 ? 6 : size;
size -= size > 6 ? 6 : size;
} while(size);
}

static void neopixel_out_masked (uint16_t device, rgb_color_t color, rgb_color_mask_t mask)
{
if(device < NEOPIXELS_NUM) {
if(neopixel.num_leds && device < neopixel.num_leds) {

rgb_1bpp_assign(&neopixel.leds[device * 3], color, mask);

device *= 3;
if(mask.G)
pixels[device++] = color.G;
else
device++;
if(mask.R)
pixels[device++] = color.R;
else
device++;
if(mask.B)
pixels[device] = color.B;
#if NEOPIXELS_NUM == 1
rmt_write_sample(neo_config.channel, pixels, sizeof(pixels), true);
neopixels_write();
#endif
//?? rmt_wait_tx_done(neo_config.channel, pdMS_TO_TICKS(100));
}
}

Expand All @@ -2481,6 +2523,20 @@ static void neopixel_out (uint16_t device, rgb_color_t color)
neopixel_out_masked(device, color, (rgb_color_mask_t){ .mask = 0xFF });
}

uint8_t neopixels_set_intensity (uint8_t value)
{
uint8_t prev = neopixel.intensity;

if(neopixel.intensity != value) {

neopixel.intensity = value;

// neopixels_write();
}

return prev;
}

#endif // NEOPIXELS_PIN

// Initializes MCU peripherals for Grbl use
Expand Down Expand Up @@ -2738,7 +2794,7 @@ bool driver_init (void)
#else
hal.info = "ESP32";
#endif
hal.driver_version = "240202";
hal.driver_version = "240205";
hal.driver_url = GRBL_URL "/ESP32";
#ifdef BOARD_NAME
hal.board = BOARD_NAME;
Expand Down Expand Up @@ -2995,7 +3051,7 @@ bool driver_init (void)
neo_config.clk_div = 2;

rmt_config(&neo_config);
rmt_driver_install(neo_config.channel, RMT_CHANNEL_MAX - 1, 0);
rmt_driver_install(neo_config.channel, 0, 0);

uint32_t counter_clk_hz = 0;

Expand All @@ -3017,6 +3073,7 @@ bool driver_init (void)
#if NEOPIXELS_NUM > 1
hal.rgb.write = neopixels_write;
#endif
hal.rgb.set_intensity = neopixels_set_intensity;
hal.rgb.num_devices = NEOPIXELS_NUM;
hal.rgb.cap = (rgb_color_t){ .R = 255, .G = 255, .B = 255 };

Expand All @@ -3038,16 +3095,18 @@ bool driver_init (void)

#if MPG_MODE == 1
#if KEYPAD_ENABLE == 2
if((hal.driver_cap.mpg_mode = stream_mpg_register(stream_open_instance(MPG_STREAM, 115200, NULL), MPG_STREAM_DUPLEX, keypad_enqueue_keycode)))
protocol_enqueue_foreground_task(modeEnable, NULL);
if((hal.driver_cap.mpg_mode = stream_mpg_register(stream_open_instance(MPG_STREAM, 115200, NULL, NULL), false, keypad_enqueue_keycode)))
protocol_enqueue_foreground_task(mpg_enable, NULL);
#else
if((hal.driver_cap.mpg_mode = stream_mpg_register(stream_open_instance(MPG_STREAM, 115200, NULL), MPG_STREAM_DUPLEX, NULL)))
protocol_enqueue_foreground_task(modeEnable, NULL);
if((hal.driver_cap.mpg_mode = stream_mpg_register(stream_open_instance(MPG_STREAM, 115200, NULL, NULL), false, NULL)))
protocol_enqueue_foreground_task(mpg_enable, NULL);
#endif
#elif MPG_MODE == 2
hal.driver_cap.mpg_mode = stream_mpg_register(stream_open_instance(MPG_STREAM, 115200, NULL), 0, keypad_enqueue_keycode);
hal.driver_cap.mpg_mode = stream_mpg_register(stream_open_instance(MPG_STREAM, 115200, NULL, NULL), false, keypad_enqueue_keycode);
#elif MPG_MODE == 3
hal.driver_cap.mpg_mode = stream_mpg_register(stream_open_instance(MPG_STREAM, 115200, NULL, NULL), false, stream_mpg_check_enable);
#elif KEYPAD_ENABLE == 2
stream_open_instance(KEYPAD_STREAM, 115200, keypad_enqueue_keycode);
stream_open_instance(KEYPAD_STREAM, 115200, keypad_enqueue_keycode, "Keypad");
#endif

#if WIFI_ENABLE
Expand Down
21 changes: 11 additions & 10 deletions main/my_machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
Copyright (c) 2020-2024 Terje Io
Grbl is free software: you can redistribute it and/or modify
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Grbl is distributed in the hope that it will be useful,
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/

// NOTE: Only one board may be enabled!
Expand Down Expand Up @@ -52,7 +52,7 @@
// Spindle definitions can be found in grbl/spindle_control.h.
// More here https://github.com/grblHAL/Plugins_spindle
//#define SPINDLE0_ENABLE SPINDLE_HUANYANG1
//#define SPINDLE0_ENABLE SPINDLE_PWM0_NODIR
//#define SPINDLE1_ENABLE SPINDLE_PWM0_NODIR
//#define SPINDLE2_ENABLE SPINDLE_NONE
//#define SPINDLE3_ENABLE SPINDLE_NONE
// **********************
Expand All @@ -64,11 +64,12 @@
//#define ETHERNET_ENABLE 1 // Ethernet streaming. Uses networking plugin.
//#define BLUETOOTH_ENABLE 1 // Set to 1 for native radio, 2 for HC-05 module.
//#define SDCARD_ENABLE 1 // Run gcode programs from SD card. Set to 2 to enable YModem upload.
//#define MPG_ENABLE 1 // Enable MPG interface. Requires serial port and one handshake pin unless
// KEYPAD_ENABLE is set to 2 when mode switching is done by the CMD_MPG_MODE_TOGGLE (0x8B)
// command character. Set both MPG_ENABLE and KEYPAD_ENABLE to 2 to use a handshake pin anyway.
//#define KEYPAD_ENABLE 1 // Set to 1 for I2C keypad, 2 for other input such as serial data. If KEYPAD_ENABLE is set to 2
// and MPG_ENABLE is uncommented then a serial stream is shared with the MPG.
//#define MPG_ENABLE 1 // Enable MPG interface. Requires a serial port and means to switch between normal and MPG mode.
// 1: Mode switching is by handshake pin input unless the keypad plugin is enabled in mode 2 which
// uses mode switching by the CMD_MPG_MODE_TOGGLE (0x8B) command character.
// 2: Mode switching is by the CMD_MPG_MODE_TOGGLE command character. The keypad plugin is not required.
//#define KEYPAD_ENABLE 1 // 1: uses a I2C keypad for input.
// 2: uses a serial port for input. If MPG_ENABLE is set to 1 the serial stream is shared with the MPG.
//#define PPI_ENABLE 1 // Laser PPI plugin. To be completed.
//#define LASER_COOLANT_ENABLE 1 // Laser coolant plugin. To be completed.
//#define LB_CLUSTERS_ENABLE 1 // LaserBurn cluster support.
Expand Down
4 changes: 1 addition & 3 deletions main/trinamic_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,8 @@ void board_init (void)

const io_stream_t *stream;

if((stream = stream_open_instance(TRINAMIC_STREAM, 230400, NULL)) == NULL)
if((stream = stream_open_instance(TRINAMIC_STREAM, 230400, NULL, "Trinamic UART")) == NULL)
stream = stream_null_init(230400);
else
stream_set_description(stream, "Trinamic UART");

if(stream) {
memcpy(&tmc_uart, stream, sizeof(io_stream_t));
Expand Down

0 comments on commit fdd4ad2

Please sign in to comment.