Skip to content

Commit

Permalink
circular shift ops
Browse files Browse the repository at this point in the history
  • Loading branch information
csboling committed Nov 16, 2019
1 parent 6401278 commit b282c93
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 23 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,9 @@
- **FIX**: improve DAC latency when using `CV` ops
- **NEW**: call metro / init with `SCRIPT 9` / `SCRIPT 10`
- **NEW**: forward (C-f or C-s) and reverse (C-r) search in help mode
- **NEW**: new ops: `LROT` (alias `<<<`), `RROT` (alias `>>>`)
- **NEW**: `LSH` and `RSH` shift the opposite direction when passed a negative shift amount
- **NEW**: new op: `SGN` (sign of argument)

## v3.1.0

Expand Down
15 changes: 14 additions & 1 deletion docs/ops/maths.toml
Expand Up @@ -116,6 +116,16 @@ prototype = "RSH x y"
aliases = [">>"]
short = "right shift `x` by `y` bits, in effect divide `x` by `2` to the power of `y`"

[LROT]
prototype = "LROT x y"
aliases = ["<<<"]
short = "circular left shift `x` by `y` bits, wrapping around when bits fall off the end"

[RROT]
prototype = "RROT x y"
aliases = [">>>"]
short = "circular right shift `x` by `y` bits, wrapping around when bits fall off the end"

["|"]
prototype = "| x y"
short = "bitwise or `x` | `y`"
Expand Down Expand Up @@ -228,6 +238,10 @@ short = "converts a voltage to a value usable by the CV outputs (`x` between `0`
prototype = "EXP x"
short = "exponentiation table lookup. `0-16383` range (V `0-10`)"

[SGN]
prototype = "SGN x"
short = "sign function: 1 for positive, -1 for negative, 0 for 0"

[CHAOS]
prototype = "CHAOS x"
short = "get next value from chaos generator, or set the current value"
Expand All @@ -251,4 +265,3 @@ short = "set the lower end of the range from 0 – 32767"
["R.MAX"]
prototype = "R.MAX x"
short = "set the upper end of the range from 0 – 32767"

6 changes: 5 additions & 1 deletion module/help_mode.c
Expand Up @@ -143,7 +143,7 @@ const char* help4[HELP4_LENGTH] = { "4/13 DATA AND TABLES",
"BPM 2-MAX|MS PER BPM",
"EXP X|EXPO LOOKUP" };

#define HELP5_LENGTH 64
#define HELP5_LENGTH 68
const char* help5[HELP5_LENGTH] = { "5/13 OPERATORS",
" ",
"RAND A|RANDOM 0 - A",
Expand All @@ -157,6 +157,8 @@ const char* help5[HELP5_LENGTH] = { "5/13 OPERATORS",
"AVG A B|AVERAGE OF INS",
"MIN A B|LESSER OF INS",
"MAX A B|GREATER OF INS",
"ABS X|ABSOLUTE VALUE",
"SGN X|SIGN FUNCTION",
" ",
"ADD A B|A + B",
"SUB A B|A - B",
Expand All @@ -176,6 +178,8 @@ const char* help5[HELP5_LENGTH] = { "5/13 OPERATORS",
" ",
"RSH A B|BITSHIFT A RIGHT B",
"LSH A B|BITSHIFT A LEFT B",
"RROT A B|BITROTATE A >> B",
"LROT A B|BITROTATE A << B",
"| A B|BITWISE A OR B",
"& A B|BITWISE A AND B",
"^ A B|BITWISE A XOR B",
Expand Down
5 changes: 5 additions & 0 deletions src/match_token.rl
Expand Up @@ -188,8 +188,11 @@
"EZ" => { MATCH_OP(E_OP_EZ); };
"RSH" => { MATCH_OP(E_OP_RSH); };
"LSH" => { MATCH_OP(E_OP_LSH); };
"RROT" => { MATCH_OP(E_OP_RROT); };
"LROT" => { MATCH_OP(E_OP_LROT); };
"EXP" => { MATCH_OP(E_OP_EXP); };
"ABS" => { MATCH_OP(E_OP_ABS); };
"SGN" => { MATCH_OP(E_OP_SGN); };
"AND" => { MATCH_OP(E_OP_AND); };
"OR" => { MATCH_OP(E_OP_OR); };
"JI" => { MATCH_OP(E_OP_JI); };
Expand Down Expand Up @@ -226,6 +229,8 @@
"!" => { MATCH_OP(E_OP_SYM_EXCLAMATION); };
"<<" => { MATCH_OP(E_OP_SYM_LEFT_ANGLED_x2); };
">>" => { MATCH_OP(E_OP_SYM_RIGHT_ANGLED_x2); };
"<<<" => { MATCH_OP(E_OP_SYM_LEFT_ANGLED_x3); };
">>>" => { MATCH_OP(E_OP_SYM_RIGHT_ANGLED_x3); };
"&&" => { MATCH_OP(E_OP_SYM_AMPERSAND_x2); };
"||" => { MATCH_OP(E_OP_SYM_PIPE_x2); };

Expand Down
86 changes: 67 additions & 19 deletions src/ops/maths.c
Expand Up @@ -66,10 +66,16 @@ static void op_RSH_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_LSH_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_RROT_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_LROT_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_EXP_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_ABS_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_SGN_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_AND_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_OR_get(const void *data, scene_state_t *ss, exec_state_t *es,
Expand Down Expand Up @@ -148,8 +154,11 @@ const tele_op_t op_NZ = MAKE_GET_OP(NZ , op_NZ_get , 1, true);
const tele_op_t op_EZ = MAKE_GET_OP(EZ , op_EZ_get , 1, true);
const tele_op_t op_RSH = MAKE_GET_OP(RSH , op_RSH_get , 2, true);
const tele_op_t op_LSH = MAKE_GET_OP(LSH , op_LSH_get , 2, true);
const tele_op_t op_RROT = MAKE_GET_OP(RROT , op_RROT_get , 2, true);
const tele_op_t op_LROT = MAKE_GET_OP(LROT , op_LROT_get , 2, true);
const tele_op_t op_EXP = MAKE_GET_OP(EXP , op_EXP_get , 1, true);
const tele_op_t op_ABS = MAKE_GET_OP(ABS , op_ABS_get , 1, true);
const tele_op_t op_SGN = MAKE_GET_OP(SGN , op_SGN_get , 1, true);
const tele_op_t op_AND = MAKE_GET_OP(AND , op_AND_get , 2, true);
const tele_op_t op_OR = MAKE_GET_OP(OR , op_OR_get , 2, true);
const tele_op_t op_JI = MAKE_GET_OP(JI , op_JI_get , 2, true);
Expand All @@ -174,22 +183,24 @@ const tele_op_t op_TIF = MAKE_GET_OP(?, op_TIF_get, 3, true);

const tele_op_t op_XOR = MAKE_ALIAS_OP(XOR, op_NE_get, NULL, 2, true);

const tele_op_t op_SYM_PLUS = MAKE_ALIAS_OP(+ , op_ADD_get, NULL, 2, true);
const tele_op_t op_SYM_DASH = MAKE_ALIAS_OP(- , op_SUB_get, NULL, 2, true);
const tele_op_t op_SYM_STAR = MAKE_ALIAS_OP(* , op_MUL_get, NULL, 2, true);
const tele_op_t op_SYM_FORWARD_SLASH = MAKE_ALIAS_OP(/ , op_DIV_get, NULL, 2, true);
const tele_op_t op_SYM_PERCENTAGE = MAKE_ALIAS_OP(% , op_MOD_get, NULL, 2, true);
const tele_op_t op_SYM_EQUAL_x2 = MAKE_ALIAS_OP(==, op_EQ_get , NULL, 2, true);
const tele_op_t op_SYM_EXCLAMATION_EQUAL = MAKE_ALIAS_OP(!=, op_NE_get , NULL, 2, true);
const tele_op_t op_SYM_LEFT_ANGLED = MAKE_ALIAS_OP(< , op_LT_get , NULL, 2, true);
const tele_op_t op_SYM_RIGHT_ANGLED = MAKE_ALIAS_OP(> , op_GT_get , NULL, 2, true);
const tele_op_t op_SYM_LEFT_ANGLED_EQUAL = MAKE_ALIAS_OP(<=, op_LTE_get, NULL, 2, true);
const tele_op_t op_SYM_RIGHT_ANGLED_EQUAL = MAKE_ALIAS_OP(>=, op_GTE_get, NULL, 2, true);
const tele_op_t op_SYM_EXCLAMATION = MAKE_ALIAS_OP(! , op_EZ_get , NULL, 1, true);
const tele_op_t op_SYM_LEFT_ANGLED_x2 = MAKE_ALIAS_OP(<<, op_LSH_get, NULL, 2, true);
const tele_op_t op_SYM_RIGHT_ANGLED_x2 = MAKE_ALIAS_OP(>>, op_RSH_get, NULL, 2, true);
const tele_op_t op_SYM_AMPERSAND_x2 = MAKE_ALIAS_OP(&&, op_AND_get, NULL, 2, true);
const tele_op_t op_SYM_PIPE_x2 = MAKE_ALIAS_OP(||, op_OR_get , NULL, 2, true);
const tele_op_t op_SYM_PLUS = MAKE_ALIAS_OP(+ , op_ADD_get, NULL, 2, true);
const tele_op_t op_SYM_DASH = MAKE_ALIAS_OP(- , op_SUB_get, NULL, 2, true);
const tele_op_t op_SYM_STAR = MAKE_ALIAS_OP(* , op_MUL_get, NULL, 2, true);
const tele_op_t op_SYM_FORWARD_SLASH = MAKE_ALIAS_OP(/ , op_DIV_get, NULL, 2, true);
const tele_op_t op_SYM_PERCENTAGE = MAKE_ALIAS_OP(% , op_MOD_get, NULL, 2, true);
const tele_op_t op_SYM_EQUAL_x2 = MAKE_ALIAS_OP(==, op_EQ_get , NULL, 2, true);
const tele_op_t op_SYM_EXCLAMATION_EQUAL = MAKE_ALIAS_OP(!=, op_NE_get , NULL, 2, true);
const tele_op_t op_SYM_LEFT_ANGLED = MAKE_ALIAS_OP(< , op_LT_get , NULL, 2, true);
const tele_op_t op_SYM_RIGHT_ANGLED = MAKE_ALIAS_OP(> , op_GT_get , NULL, 2, true);
const tele_op_t op_SYM_LEFT_ANGLED_EQUAL = MAKE_ALIAS_OP(<=, op_LTE_get, NULL, 2, true);
const tele_op_t op_SYM_RIGHT_ANGLED_EQUAL = MAKE_ALIAS_OP(>=, op_GTE_get, NULL, 2, true);
const tele_op_t op_SYM_EXCLAMATION = MAKE_ALIAS_OP(! , op_EZ_get , NULL, 1, true);
const tele_op_t op_SYM_LEFT_ANGLED_x2 = MAKE_ALIAS_OP(<<, op_LSH_get, NULL, 2, true);
const tele_op_t op_SYM_RIGHT_ANGLED_x2 = MAKE_ALIAS_OP(>>, op_RSH_get, NULL, 2, true);
const tele_op_t op_SYM_LEFT_ANGLED_x3 = MAKE_ALIAS_OP(<<<, op_LROT_get, NULL, 2, true);
const tele_op_t op_SYM_RIGHT_ANGLED_x3 = MAKE_ALIAS_OP(>>>, op_RROT_get, NULL, 2, true);
const tele_op_t op_SYM_AMPERSAND_x2 = MAKE_ALIAS_OP(&&, op_AND_get, NULL, 2, true);
const tele_op_t op_SYM_PIPE_x2 = MAKE_ALIAS_OP(||, op_OR_get , NULL, 2, true);
// clang-format on


Expand Down Expand Up @@ -427,12 +438,44 @@ static void op_EZ_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),

static void op_RSH_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
cs_push(cs, cs_pop(cs) >> cs_pop(cs));
int16_t x = cs_pop(cs);
int16_t n = cs_pop(cs);
cs_push(cs, (n > 0) ? (x >> n) : (x << -n));
}

static void op_LSH_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
cs_push(cs, cs_pop(cs) << cs_pop(cs));
int16_t x = cs_pop(cs);
int16_t n = cs_pop(cs);
cs_push(cs, (n > 0) ? (x << n) : (x >> -n));
}

static uint16_t rrot(uint16_t x, uint8_t n) {
return (x >> n) | (x << (16 - n));
}

static uint16_t lrot(uint16_t x, uint8_t n) {
return (x << n) | (x >> (16 - n));
}

typedef union { int16_t si; uint16_t ui; } bits16;

static void op_RROT_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
bits16 u;
u.si = cs_pop(cs);
int16_t n = cs_pop(cs) % 16;
u.ui = (n > 0) ? rrot(u.ui, n) : lrot(u.ui, -n);
cs_push(cs, u.si);
}

static void op_LROT_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
bits16 u;
u.si = cs_pop(cs);
int16_t n = cs_pop(cs) % 16;
u.ui = (n > 0) ? lrot(u.ui, n) : rrot(u.ui, -n);
cs_push(cs, u.si);
}

static void op_EXP_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
Expand Down Expand Up @@ -463,6 +506,12 @@ static void op_ABS_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
cs_push(cs, a);
}

static void op_SGN_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
int16_t a = cs_pop(cs);
cs_push(cs, (a > 0) ? 1 : ((a < 0) ? -1 : 0));
}

static void op_AND_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
int16_t a = cs_pop(cs);
Expand Down Expand Up @@ -703,4 +752,3 @@ static void op_TIF_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
s16 b = cs_pop(cs);
cs_push(cs, condition ? a : b);
}

5 changes: 5 additions & 0 deletions src/ops/maths.h
Expand Up @@ -33,8 +33,11 @@ extern const tele_op_t op_NZ;
extern const tele_op_t op_EZ;
extern const tele_op_t op_RSH;
extern const tele_op_t op_LSH;
extern const tele_op_t op_RROT;
extern const tele_op_t op_LROT;
extern const tele_op_t op_EXP;
extern const tele_op_t op_ABS;
extern const tele_op_t op_SGN;
extern const tele_op_t op_AND;
extern const tele_op_t op_OR;
extern const tele_op_t op_JI;
Expand Down Expand Up @@ -73,6 +76,8 @@ extern const tele_op_t op_SYM_RIGHT_ANGLED_EQUAL; // >= alias GT
extern const tele_op_t op_SYM_EXCLAMATION; // ! alias NZ
extern const tele_op_t op_SYM_LEFT_ANGLED_x2; // << alias LSH
extern const tele_op_t op_SYM_RIGHT_ANGLED_x2; // >> alias RSH
extern const tele_op_t op_SYM_LEFT_ANGLED_x3; // <<< alias LROT
extern const tele_op_t op_SYM_RIGHT_ANGLED_x3; // >>> alias RROT
extern const tele_op_t op_SYM_AMPERSAND_x2; // && alias AND
extern const tele_op_t op_SYM_PIPE_x2; // || alias OR

Expand Down
6 changes: 4 additions & 2 deletions src/ops/op.c
Expand Up @@ -80,14 +80,16 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = {
&op_ADD, &op_SUB, &op_MUL, &op_DIV, &op_MOD, &op_RAND, &op_RND, &op_RRAND,
&op_RRND, &op_R, &op_R_MIN, &op_R_MAX, &op_TOSS, &op_MIN, &op_MAX, &op_LIM,
&op_WRAP, &op_WRP, &op_QT, &op_AVG, &op_EQ, &op_NE, &op_LT, &op_GT, &op_LTE,
&op_GTE, &op_NZ, &op_EZ, &op_RSH, &op_LSH, &op_EXP, &op_ABS, &op_AND,
&op_OR, &op_JI, &op_SCALE, &op_SCL, &op_N, &op_V, &op_VV, &op_ER, &op_BPM,
&op_GTE, &op_NZ, &op_EZ, &op_RSH, &op_LSH, &op_LROT, &op_RROT,
&op_EXP, &op_ABS, &op_SGN, &op_AND, &op_OR,
&op_JI, &op_SCALE, &op_SCL, &op_N, &op_V, &op_VV, &op_ER, &op_BPM,
&op_BIT_OR, &op_BIT_AND, &op_BIT_NOT, &op_BIT_XOR, &op_BSET, &op_BGET,
&op_BCLR, &op_XOR, &op_CHAOS, &op_CHAOS_R, &op_CHAOS_ALG, &op_SYM_PLUS,
&op_SYM_DASH, &op_SYM_STAR, &op_SYM_FORWARD_SLASH, &op_SYM_PERCENTAGE,
&op_SYM_EQUAL_x2, &op_SYM_EXCLAMATION_EQUAL, &op_SYM_LEFT_ANGLED,
&op_SYM_RIGHT_ANGLED, &op_SYM_LEFT_ANGLED_EQUAL, &op_SYM_RIGHT_ANGLED_EQUAL,
&op_SYM_EXCLAMATION, &op_SYM_LEFT_ANGLED_x2, &op_SYM_RIGHT_ANGLED_x2,
&op_SYM_LEFT_ANGLED_x3, &op_SYM_RIGHT_ANGLED_x3,
&op_SYM_AMPERSAND_x2, &op_SYM_PIPE_x2, &op_TIF,

// stack
Expand Down
5 changes: 5 additions & 0 deletions src/ops/op_enum.h
Expand Up @@ -161,8 +161,11 @@ typedef enum {
E_OP_EZ,
E_OP_RSH,
E_OP_LSH,
E_OP_LROT,
E_OP_RROT,
E_OP_EXP,
E_OP_ABS,
E_OP_SGN,
E_OP_AND,
E_OP_OR,
E_OP_JI,
Expand Down Expand Up @@ -198,6 +201,8 @@ typedef enum {
E_OP_SYM_EXCLAMATION,
E_OP_SYM_LEFT_ANGLED_x2,
E_OP_SYM_RIGHT_ANGLED_x2,
E_OP_SYM_LEFT_ANGLED_x3,
E_OP_SYM_RIGHT_ANGLED_x3,
E_OP_SYM_AMPERSAND_x2,
E_OP_SYM_PIPE_x2,
E_OP_TIF,
Expand Down

0 comments on commit b282c93

Please sign in to comment.