chiark / gitweb /
changelog: sort out a bit
[chiark-tcl.git] / wiringpi / wiringpi.c
index f3b7cb8f3e64650ee4fefbe4e41814333a2942a4..eaf05eb5320cac49636595f03cb3e0f4ab07e380 100644 (file)
 
 /*---------- important types and forward declarations ----------*/
 
-static int ensure_setup(void) {
-  return TCL_OK;
-}
-
-/*---------- operations ----------*/
-
 #define CHECK_SETUP                            \
   int rc;                                      \
-  rc = ensure_setup();                         \
+  rc = ensure_setup(ip);                       \
   if (rc) return rc; else
 
 #define CHECK_RANGE(val, min, max, what, VAL) do{              \
@@ -75,10 +69,59 @@ static int ensure_setup(void) {
                           "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);
+static int setup_done;
+
+/*---------- operations ----------*/
+
+static int setup_failure(Tcl_Interp *ip, int r) {
+#define N 4
+  Tcl_Obj *codelist[N];
+  codelist[0]= cht_ret_string(ip,"WIRINGPI");
+  codelist[1]= cht_ret_string(ip,"ERROR");
+  codelist[2]= cht_ret_string(ip,"SETUP");
+  codelist[3]= cht_ret_int(ip,r);
+  Tcl_SetObjResult(ip, Tcl_NewListObj(N, codelist));
+#undef N
+  Tcl_SetResult(ip, (char*)"wiringpi initialisation error", TCL_STATIC);
+  return TCL_ERROR;
+}
+
+static int ensure_setup(Tcl_Interp *ip) {
+  if (!setup_done) {
+    int r = wiringPiSetup();
+    if (r) return setup_failure(ip, r);
+    setup_done = 1;
+  }
+  return TCL_OK;
+}
+
+int cht_do_wiringpitcl_setup(ClientData cd, Tcl_Interp *ip,
+                            int objc, Tcl_Obj *const *objv) {
+  int r;
+  int rc;
+
+  if (setup_done)
+    return cht_staticerr(ip,"wiringpi setup called again",
+                        "WIRINGPI FORBIDDEN-REINIT SETUP");
+
+  if (*objv) {
+    const char *modeopt;
+    rc = cht_pat_string(ip,*objv++,&modeopt);
+    if (rc) return rc;
+    if (modeopt[0] != '-' || !modeopt[1] || modeopt[2])
+      return cht_staticerr(ip,"wiringpi setup option wrong syntax", 0);
+    if (*objv)
+      return cht_staticerr(ip,"wiringpi setup too many arguments", 0);
+    switch (modeopt[1]) {
+    case 'g':  r = wiringPiSetupGpio();                             break;
+    case '1':  r = wiringPiSetupPhys();                             break;
+    default:
+      return cht_staticerr(ip,"wiringpi setup option unknown value", 0);
+    }
+  } else {
+    r = wiringPiSetup();
+  }
+  if (r) return setup_failure(ip, r);
   return TCL_OK;
 }
 
@@ -94,7 +137,7 @@ int cht_do_wiringpitcl_boardId(ClientData cd, Tcl_Interp *ip,
            &ints[3],
            &ints[4]);
   int i;
-  for (i=0; i<N; i++) objl[i]= Tcl_NewIntObj(ints[i]);
+  for (i=0; i<N; i++) objl[i]= cht_ret_int(ip, ints[i]);
   *result= Tcl_NewListObj(N,objl);
   return TCL_OK;
 #undef N
@@ -106,14 +149,45 @@ int cht_do_wiringpitcl_boardRev(ClientData cd, Tcl_Interp *ip, int *result) {
   return TCL_OK;
 }
 
-/*---------- families operations ----------*/
+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_pwmr(ClientData cd, Tcl_Interp *ip, int range) {
+  CHECK_SETUP;
+  CHECK_RANGE(range,1,INT_MAX,"pwm range","RANGE");
+  pwmSetRange(range);
+  return TCL_OK;
+}
+
+int cht_do_wiringpitcl_pwm_bal(ClientData cd, Tcl_Interp *ip) {
+  CHECK_SETUP;
+  pwmSetMode(PWM_MODE_BAL);
+  return TCL_OK;
+}
 
-int cht_do_wiringpitcl_aread(ClientData cd, Tcl_Interp *ip, int pin, int *result) {
+int cht_do_wiringpitcl_pwm_ms(ClientData cd, Tcl_Interp *ip) {
   CHECK_SETUP;
-  *result = analogRead(pin);
+  pwmSetMode(PWM_MODE_MS);
   return TCL_OK;
 }
 
+/*---------- families of operations ----------*/
+
+#define SIMPLE_READER_OP(op, wpicall)                          \
+  int cht_do_wiringpitcl_##op(ClientData cd, Tcl_Interp *ip,   \
+                               int pin, int *result) {         \
+    CHECK_SETUP;                                               \
+    *result = wpicall(pin);                                    \
+    return TCL_OK;                                             \
+  }
+
+SIMPLE_READER_OP(read,  digitalRead)
+SIMPLE_READER_OP(aread, analogRead)
+
 #define SIMPLE_WRITER_OP(op, min, max, wpicall)                        \
   int cht_do_wiringpitcl_##op(ClientData cd, Tcl_Interp *ip,   \
                              int pin, int val) {               \
@@ -159,8 +233,7 @@ const WiringPiTclModeInfo cht_wiringpitclmodeinfo_entries[] = {
 
 int cht_do_wiringpitcl_mode(ClientData cd, Tcl_Interp *ip, int pin,
                            const WiringPiTclModeInfo *mode) {
-  int rc;
-  rc = ensure_setup();  if (rc) return rc;
+  CHECK_SETUP;
   mode->func(pin);
   return TCL_OK;
 }