Permalink
Browse files

feat: quick&dirty implementation of Pin.stepper()

for precisely controlling Stepper motors without CPU supervision
  • Loading branch information...
urish committed Oct 22, 2017
1 parent afec961 commit c649db00a8af92b1ae25c5fdf7ec277422a531ba
Showing with 114 additions and 0 deletions.
  1. +113 −0 src/jswrap_pin.c
  2. +1 −0 src/jswrap_pin.h
@@ -17,6 +17,11 @@
#include "jswrap_io.h"
#include "jstimer.h"

#include "nrf_drv_gpiote.h"
#include "nrf_drv_ppi.h"
#include "nrf_timer.h"
#include "nrf_pwm.h"

/*JSON{
"type" : "class",
"class" : "Pin",
@@ -167,6 +172,114 @@ void jswrap_pin_mode(JsVar *parent, JsVar *mode) {
jswrap_io_pinMode(jshGetPinFromVar(parent), mode, false);
}

static int get_counter(JsVarFloat freq, int *clk) {
int counter = (int)(16000000.0 / freq / 2);

if (counter<32768) {
*clk = NRF_PWM_CLK_16MHz;
if (counter<1) counter=1;
} else if (counter < (32768<<1)) {
*clk = NRF_PWM_CLK_8MHz;
counter >>= 1;
} else if (counter < (32768<<2)) {
*clk = NRF_PWM_CLK_4MHz;
counter >>= 2;
} else if (counter < (32768<<3)) {
*clk = NRF_PWM_CLK_2MHz;
counter >>= 3;
} else if (counter < (32768<<4)) {
*clk = NRF_PWM_CLK_1MHz;
counter >>= 4;
} else if (counter < (32768<<5)) {
*clk = NRF_PWM_CLK_500kHz;
counter >>= 5;
} else if (counter < (32768<<6)) {
*clk = NRF_PWM_CLK_250kHz;
counter >>= 6;
} else {
*clk = NRF_PWM_CLK_125kHz;
counter >>= 7;
}

return counter;
}

/*JSON{
"type" : "method",
"class" : "Pin",
"name" : "stepper",
"generate" : "jswrap_pin_stepper",
"params" : [
["freq", "float", "Step frequency"],
["count", "int", "Step count"]
]
}
*/
void jswrap_pin_stepper(JsVar *parent, JsVarFloat freq, JsVarInt count) {
uint32_t err_code;

static initialized = false;
static nrf_ppi_channel_t ppi_channel1, ppi_channel2, ppi_channel3;

Pin p = jshGetPinFromVar(parent);
nrf_drv_gpiote_out_config_t txconfig = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
nrf_drv_gpiote_out_init(p, &txconfig);
nrf_drv_gpiote_out_task_enable(p);

nrf_timer_mode_set(NRF_TIMER3, TIMER_MODE_MODE_Timer);
nrf_timer_bit_width_set(NRF_TIMER3, NRF_TIMER_BIT_WIDTH_16);
int clk = NRF_PWM_CLK_125kHz;
int counter = get_counter(freq, &clk);
nrf_timer_frequency_set(NRF_TIMER3, clk);
nrf_timer_cc_write(NRF_TIMER3, 0, counter);
nrf_timer_shorts_enable(NRF_TIMER3, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK);

nrf_timer_mode_set(NRF_TIMER2, TIMER_MODE_MODE_Counter);
nrf_timer_task_trigger(NRF_TIMER2, NRF_TIMER_TASK_CLEAR);
nrf_timer_bit_width_set(NRF_TIMER2, NRF_TIMER_BIT_WIDTH_32);
nrf_timer_cc_write(NRF_TIMER2, 0, count * 2);

if (!initialized) {
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_ppi_channel_alloc(&ppi_channel2);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_ppi_channel_alloc(&ppi_channel3);
APP_ERROR_CHECK(err_code);

initialized = true;
}

err_code = nrf_drv_ppi_channel_assign(ppi_channel1,
nrf_timer_event_address_get(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE0),
nrf_drv_gpiote_out_task_addr_get(p));
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_ppi_channel_assign(ppi_channel2,
nrf_timer_event_address_get(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE0),
nrf_timer_task_address_get(NRF_TIMER2, NRF_TIMER_TASK_COUNT));
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_ppi_channel_assign(ppi_channel3,
nrf_timer_event_address_get(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE0),
nrf_timer_task_address_get(NRF_TIMER3, NRF_TIMER_TASK_STOP));
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(ppi_channel3);
APP_ERROR_CHECK(err_code);

nrf_timer_task_trigger(NRF_TIMER2, NRF_TIMER_TASK_START);
nrf_timer_task_trigger(NRF_TIMER3, NRF_TIMER_TASK_START);

nrf_gpio_cfg_output(p);
}

/*JSON{
"type" : "method",
"class" : "Pin",
@@ -22,5 +22,6 @@ void jswrap_pin_write(JsVar *parent, bool value);
void jswrap_pin_writeAtTime(JsVar *parent, bool value, JsVarFloat time);
JsVar *jswrap_pin_getMode(JsVar *parent);
void jswrap_pin_mode(JsVar *parent, JsVar *mode);
void jswrap_pin_stepper(JsVar *parent, JsVarFloat freq, JsVarInt count);
bool jswrap_pin_toggle(JsVar *parent);
JsVar *jswrap_pin_getInfo(JsVar *parent);

0 comments on commit c649db0

Please sign in to comment.