--- /dev/null
+/**/
+
+#include <assert.h>
+
+#include "hostside.h"
+
+#define XCONST(d) const Byte c[2]= { d }; XMIT;
+
+static Byte *addr(int addr, Byte *ap) {
+ /* encodes decoder address */
+ assert(addr>0 && addr<=0x3ff);
+ if (addr < 0x3f) {
+ /* Short addresses: S9.2 B l.41 which is the same as RP9.2.1 C l.65
+ * first sentence. */
+ *--ap= addr;
+ } else {
+ /* Long addresses: RP9.2.1 C l.65-69. */
+ *--ap= addr;
+ *--ap= (addr >> 8) | 0xc0;
+ }
+ return ap;
+}
+
+#define ADDR Byte *c= addr(addr, p->d);
+#define ENCD p->l= c - p->d; assert(p->l <= sizeof(p->d));
+
+void enco_nmra_speed28(Nmra *p, int addr, int speed, int reverse) {
+ /* Baseline Speed and Direction, S9.2 B (for short addresses
+ * only), which is also identical to Multi-Function Decoder
+ * Speed and Direction RP9.2.1 C l.215- (defined for both
+ * addresses), so actually the address format and instruction
+ * format are independent.
+ */
+ int adj;
+ ADDR;
+
+ assert(speed>=0 && speed<=28);
+ *c++= 0x40 | (reverse ? 0 : 0x20);
+ if (speed) {
+ adj= speed + 3;
+ *c |= adj & 1 ? 0x10 : 0;
+ *c |= adj >> 1;
+ }
+ c++;
+ ENCD;
+}
+
+void enco_nmra_estop1(Nmra *p, int addr) {
+ /* Baseline Speed and direction Forwards E-Stop(I) S9.2 B table l.56 */
+ ADDR;
+ *c++= 0x71;
+ ENCD;
+}
+
+void enco_nmra_estop(void) {
+ /* Baseline Broadcast stop Forwards(I) Emergency S9.2 B l.98- */
+ XCONST(0x00, 0x71);
+}
+void enco_nmra_reset(void) {
+ /* Baseline Decoder Reset S9.2 B l.77- */
+ XCONST(0x00, 0x00);
+}
+void enco_nmra_idle(void) {
+ /* Baseline Idle S9.2 B l.87- */
+ XCONST(0xff, 0x00);
+}
+
+void enco_nmra_speed126(int addr, int speed, int reverse) {
+ /* Advanced Operations 128 Speed Step Control
+ * (actually speeds 0..126) RP9.2.1 C l.200- */
+ CMD(2);
+ ADDR;
+ assert(speed>=0 && speed<=126);
+ c[0]= 0x3f;
+ c[1]= (speed ? speed + 1 : 0) | (reverse ? 0 : 0x80);
+ ENCD;
+}
+
+void enco_nmra_funcs0to4(unsigned bitmap) {
+ /* Function Group One RP9.2.1 C l.234- */
+ CMD(1);
+ ADDR;
+ FUNCS;
+ c[0]= 0x80 | ((bitmap >> 1) & 0x0f) | ((bitmap << 4 & 0x10));
+ ENCD;
+}
+void enco_nmra_funcs5to9(unsigned bitmap) {
+ /* Function Group Two RP9.2.1 C l.246- */
+ CMD(1);
+ ADDR;
+ FUNCS;
+ c[0]= 0xa0 | ((bitmap >> 5) & 0x0f);
+ ENCD;
+}
+void enco_nmra_funcs9to12(unsigned bitmap) {
+ /* Function Group Two RP9.2.1 C l.246- */
+ CMD(1);
+ ADDR;
+ FUNCS;
+ c[0]= 0xb0 | ((bitmap >> 9) & 0x0f);
+ ENCD;
+}
+
+void enco_nmra_cv_write(int addr, int cv, Byte value) {
+ /* Configuration Variable Access Long Form RP9.2.1 C l.286- */
+ int adj;
+ CMD(3);
+ ADDR;
+ assert(cv>=1 && cv<=1024);
+ adj= cv - 1;
+ c[0]= 0xec | (adj >> 8);
+ c[1]= adj;
+ c[2]= value;
+ ENCD;
+}
+
#define COMMAND_ENCODED_MAX 16
#define NMRA_PACKET_MAX ((COMMAND_ENCODED_MAX*7 - 14) / 8)
+typedef struct Nmra {
+ Byte d[NMRA_PACKET_MAX];
+ int l;
+} Nmra;
+
void xmit_nmra_raw(const Byte *with_csum, int length);
-void xmit_nmra(const Byte *without_csum, int length);
+void xmit_nmra_bytes(const Byte *without_csum, int length);
+void xmit_nmra(const Nmra*);
void xmit_command(const Byte *command, int length);
+void enco_nmra_speed28(Nmra *p, int train, int speed, int reverse);
+void enco_nmra_speed126(Nmra *p, int addr, int speed, int reverse);
+ /* 0<=speed<=28 or <=126; reverse: 0 forwards, non-0 backwards */
+void enco_nmra_funcs0to4(Nmra *p, unsigned bitmap);
+void enco_nmra_funcs5to8(Nmra *p, unsigned bitmap);
+void enco_nmra_funcs9to12(Nmra *p, unsigned bitmap);
+ /* bit 0 is FL aka F0; bits 1-12 are F1-F12; do not call with bits
+ * outside 0-12 set; bits in 0-12 but not relevant for the relevant
+ * command are ignored. */
+void enco_nmra_cv_write(Nmra *p, int addr, int cv, Byte value);
+
+void enco_nmra_idle(Nmra *p);
+void enco_nmra_reset(Nmra *p);
+void enco_nmra_estop(Nmra *p);
+void enco_nmra_estop1(Nmra *p);
+
extern FILE *dump_stream;
void dump(const char *what, const Byte *data, int length);
void sysfatal(const char *m);
--- /dev/null
+
+
+NMRA(speed28, Aint(addr) Aint(speed) Aint(reverse), {
+ int adj;
+
+ assert(speed>=0 && speed<=28);
+ *c++= 0x40 | (reverse ? 0 : 0x20);
+ if (speed) {
+ adj= speed + 3;
+ *c |= adj & 1 ? 0x10 : 0;
+ *c |= adj >> 1;
+ }
+ c++;
+});
+
+NMRA(
+
+
+
+ /* Baseline Speed and Direction, S9.2 B (for short addresses
+ * only), which is also identical to Multi-Function Decoder
+ * Speed and Direction RP9.2.1 C l.215- (defined for both
+ * addresses), so actually the address format and instruction
+ * format are independent.
+ */
+ ADDR;
+
+ ENCD;
+}