chiark / gitweb /
wiringpi: much implementation
[chiark-tcl.git] / wiringpi / wiringpi.c
index e71cb53..f3b7cb8 100644 (file)
  *   write PIN VAL
  *   pwm PIN VAL
  *   clock PIN FREQ
- *   drive GROUP VALUE
- *   pwm-bal|pwm-ms PIN
- *   pwmr PIN RANGE
- *   pwmc PIN CLOCK
+ *   pwm-bal|pwm-ms
+ *   pwmr RANGE
+ *   pwmc DIVIDER
  *   pwmTone PIN FREQ
  */
 /* ---8<--- end of documentation comment --8<-- */
 
 #include "chiark_tcl_wiringpi.h"
 
+#include "wiringPi.h"
+
 /*---------- important types and forward declarations ----------*/
 
+static int ensure_setup(void) {
+  return TCL_OK;
+}
+
+/*---------- operations ----------*/
+
+#define CHECK_SETUP                            \
+  int rc;                                      \
+  rc = ensure_setup();                         \
+  if (rc) return rc; else
+
+#define CHECK_RANGE(val, min, max, what, VAL) do{              \
+    if (val < (min))                                           \
+      return cht_staticerr(ip, what " too small"               \
+                          " (must be at least" #min ")",       \
+                          "WIRINGPI RANGE " VAL " MIN " #min); \
+    if (val > (max))                                           \
+      return cht_staticerr(ip, what " too large"               \
+                          " (must be at most" #max ")",        \
+                          "WIRINGPI RANGE " VAL " MAX " #max); \
+  }while(0)
+
+int cht_do_wiringpitcl_pwmc(ClientData cd, Tcl_Interp *ip, int divider) {
+  CHECK_SETUP;
+  CHECK_RANGE(divider,1,4095,"divider for pwmc","DIVIDER");
+  pwmSetClock(divider);
+  return TCL_OK;
+}
+
+int cht_do_wiringpitcl_boardId(ClientData cd, Tcl_Interp *ip,
+                              Tcl_Obj **result) {
+#define N 5
+  CHECK_SETUP;
+  int ints[N];
+  Tcl_Obj *objl[N];
+  piBoardId(&ints[0],
+           &ints[1],
+           &ints[2],
+           &ints[3],
+           &ints[4]);
+  int i;
+  for (i=0; i<N; i++) objl[i]= Tcl_NewIntObj(ints[i]);
+  *result= Tcl_NewListObj(N,objl);
+  return TCL_OK;
+#undef N
+}
+
+int cht_do_wiringpitcl_boardRev(ClientData cd, Tcl_Interp *ip, int *result) {
+  CHECK_SETUP;
+  *result = piBoardRev();
+  return TCL_OK;
+}
+
+/*---------- families operations ----------*/
+
+int cht_do_wiringpitcl_aread(ClientData cd, Tcl_Interp *ip, int pin, int *result) {
+  CHECK_SETUP;
+  *result = analogRead(pin);
+  return TCL_OK;
+}
+
+#define SIMPLE_WRITER_OP(op, min, max, wpicall)                        \
+  int cht_do_wiringpitcl_##op(ClientData cd, Tcl_Interp *ip,   \
+                             int pin, int val) {               \
+    CHECK_SETUP                                                        \
+    CHECK_RANGE(val,min,max, "value for " #op, "VAL");         \
+    wpicall(pin, val);                                         \
+    return TCL_OK;                                             \
+  }
+
+SIMPLE_WRITER_OP(pwm,     INT_MIN,INT_MAX, pwmWrite)
+SIMPLE_WRITER_OP(awrite,  INT_MIN,INT_MAX, analogWrite)
+SIMPLE_WRITER_OP(write,   0,      1,       digitalWrite)
+SIMPLE_WRITER_OP(pwmTone, INT_MIN,INT_MAX, pwmToneWrite)
+SIMPLE_WRITER_OP(clock,   INT_MIN,INT_MAX, gpioClockSet)
+
+#define MODES(M)                                               \
+  M(in,       { pinMode        (pin, INPUT); })                        \
+  M(input,    { pinMode        (pin, INPUT); })                        \
+  M(out,      { pinMode        (pin, OUTPUT); })               \
+  M(output,   { pinMode        (pin, OUTPUT); })               \
+  M(pwm,      { pinMode        (pin, PWM_OUTPUT); })           \
+  M(pwmTone,  { pinMode        (pin, PWM_TONE_OUTPUT); })      \
+  M(clock,    { pinMode        (pin, GPIO_CLOCK); })           \
+  M(up,       { pullUpDnControl(pin, PUD_UP); })               \
+  M(down,     { pullUpDnControl(pin, PUD_DOWN); })             \
+  M(tri,      { pullUpDnControl(pin, PUD_OFF); })              \
+  M(off,      { pullUpDnControl(pin, PUD_OFF); })              \
+  M(alt0,     { pinModeAlt(pin, 0b100); })                     \
+  M(alt1,     { pinModeAlt(pin, 0b101); })                     \
+  M(alt2,     { pinModeAlt(pin, 0b110); })                     \
+  M(alt3,     { pinModeAlt(pin, 0b111); })                     \
+  M(alt4,     { pinModeAlt(pin, 0b011); })                     \
+  M(alt5,     { pinModeAlt(pin, 0b010); })
+
+#define MODE_FUNC(name, body) static void mode_##name(int pin) { body }
+  MODES(MODE_FUNC)
+
+const WiringPiTclModeInfo cht_wiringpitclmodeinfo_entries[] = {
+#define MODEINFO_ENTRY(name, body) { #name, mode_##name },
+  MODES(MODEINFO_ENTRY)
+  { 0 },
+};
+
+int cht_do_wiringpitcl_mode(ClientData cd, Tcl_Interp *ip, int pin,
+                           const WiringPiTclModeInfo *mode) {
+  int rc;
+  rc = ensure_setup();  if (rc) return rc;
+  mode->func(pin);
+  return TCL_OK;
+}
+
+
 /*---------- main hooks for tcl ----------*/
 
 CHT_INIT(wiringpi, {}, CHTI_COMMANDS(cht_wiringpitoplevel_entries))