chiark / gitweb /
sort of before mangle things into nmra-packets.h
authorian <ian>
Tue, 11 Jan 2005 22:16:43 +0000 (22:16 +0000)
committerian <ian>
Tue, 11 Jan 2005 22:16:43 +0000 (22:16 +0000)
hostside/encode.c [new file with mode: 0644]
hostside/hostside.h
hostside/nmra-packets.h [new file with mode: 0644]
hostside/nmra.c

diff --git a/hostside/encode.c b/hostside/encode.c
new file mode 100644 (file)
index 0000000..eb417bc
--- /dev/null
@@ -0,0 +1,116 @@
+/**/
+
+#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;
+}
+
index f3659bcc6ce05b7ec792903f0029384573374b67..31a0775a6b8c3378fb502b6624cafb844f7630c0 100644 (file)
@@ -8,10 +8,32 @@ typedef unsigned char Byte;
 #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);
diff --git a/hostside/nmra-packets.h b/hostside/nmra-packets.h
new file mode 100644 (file)
index 0000000..42bf03f
--- /dev/null
@@ -0,0 +1,29 @@
+
+
+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;
+}
index 51bd88f13c6ce06a45f2e6a964adc3f6120d663d..606d7159a3b7c83a098b6bd8e06963331e4aee18 100644 (file)
@@ -48,7 +48,8 @@ void xmit_nmra_raw(const Byte *nmra_packet, int length) {
   xmit_command(encoded, encp - encoded);
 }
 
-void xmit_nmra(const Byte *without_csum, int length) {
+void xmit_nmra_bytes(const Byte *without_csum, int length) {
+  /* calculates checksum, S9.2 B l.63 */
   Byte with_csum[NMRA_PACKET_MAX];
   const Byte *in;
   Byte *out;