The Squirrel interpreter for FRDM-K64F, extended with a set of classes that provide access to the mbed functionality (currently DigitalIn, DigitalInOut, DigitalOut, InterruptIn, PwmOut, Ticker, Timeout, Timer).

Dependencies:   SQUIRREL3 mbed sqbind-0_99

The Squirrel interpreter for FRDM-K64F.

NOTE: Currently of POC quality.

See http://www.squirrel-lang.org/ for information about the Squirrel language.

Currently the following (a subset of their functionality) mbed classes are available from within Squirrel:

  • DigitalIn
  • DigitalOut
  • DigitalInOut
  • PwmOut
  • Ticker
  • Timeout
  • Timer

In addition, InterruptIn is supported, but interrupts are noted when they occur, but only delivered from the main loop of the interpreter.

See also README.txt in the root of the project.

Revision:
0:6f55c7651ccc
Child:
1:540008bb92a2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sqmbed/src/interruptin.cpp	Tue Dec 16 12:54:53 2014 +0000
@@ -0,0 +1,142 @@
+/*
+  @License@
+*/
+
+#include <sqmbed/interruptin.h>
+#include <sqmbed/pointerstorage.h>
+
+namespace
+{
+
+class Interrupts : public SqMbed::PointerStorage<SqMbed::InterruptIn>
+{
+public:
+    static void notify(PinName pin) {
+        // Do not store pointers here. Who knows, maybe the handler creates a
+        // new InterruptIn and then both s_nSpace and s_ppInterrupts may change.
+        for (uint32_t i = 0; i < s_nSpace; ++i) {
+            SqMbed::InterruptIn* pInterrupt = s_ppObjects[i];
+
+            if (pInterrupt && (pInterrupt->pin() == pin)) {
+                pInterrupt->call();
+            }
+        }
+    }
+};
+
+}
+
+template<>
+struct SqBindAllocator<SqMbed::InterruptIn> {
+    static SQBIND_INLINE SqMbed::InterruptIn *construct(HSQUIRRELVM) {
+        return NULL; // make it not able to construct
+    }
+
+    static SQBIND_INLINE SqMbed::InterruptIn *copy_construct(const SqMbed::InterruptIn* p_from) {
+        return NULL; // make it not able to copy-construct
+    }
+
+    static SQBIND_INLINE bool assign(SqMbed::InterruptIn* p_val, const SqMbed::InterruptIn* p_from) {
+        return false; // make it not able to assign
+    }
+
+    static SQBIND_INLINE void destruct(SqMbed::InterruptIn* p_instance) {
+        delete p_instance;
+    }
+
+    static SQBIND_INLINE SqMbed::InterruptIn& get_empty() {
+        // if someone tries to assign, this will crash.
+        // however, this will likely never be called anyway.
+        static SqMbed::InterruptIn *crashplease=NULL;
+        return *crashplease;
+    }
+};
+
+namespace SqMbed
+{
+
+InterruptIn::InterruptIn(HSQUIRRELVM vm, PinName pin)
+    : m_vm(vm)
+    , m_pin(pin)
+    , m_intIn(pin)
+{
+    m_object._type = OT_NULL;
+
+    Interrupts::add(this);
+}
+
+void InterruptIn::rise(HSQOBJECT o)
+{
+    if (m_object._type != OT_NULL) {
+        sq_release(m_vm, &m_object);
+        m_object._type = OT_NULL;
+    }
+
+    m_object = o;
+    sq_addref(m_vm, &m_object);
+
+    m_intIn.rise(this, &InterruptIn::raised);
+}
+
+InterruptIn::~InterruptIn()
+{
+    Interrupts::remove(this);
+}
+
+void InterruptIn::raised()
+{
+    InterruptIn::postponeInterrupt(m_pin);
+}
+
+void InterruptIn::call()
+{
+    int top = sq_gettop(m_vm);
+    sq_pushobject(m_vm, m_object); // The function
+    sq_pushroottable(m_vm);        // This
+    sq_call(m_vm, 1, 0, 0);        // Only this as argument.
+    sq_settop(m_vm, top);          // Restore the stack.
+}
+
+// static
+void InterruptIn::deliver(PinName pin)
+{
+    Interrupts::notify(pin);
+}
+
+// static
+void InterruptIn::bind(HSQUIRRELVM vm)
+{
+    SqBind<InterruptIn>::init(vm, _SC("InterruptIn"));
+    SqBind<InterruptIn>::set_custom_constructor(&InterruptIn::constructor);
+
+    sqbind_method(vm, "rise", &InterruptIn::rise);
+    sqbind_method(vm, "call", &InterruptIn::call);
+}
+
+// static
+InterruptIn* InterruptIn::constructor(HSQUIRRELVM vm)
+{
+    InterruptIn* pThis = 0;
+
+    int nParams = sq_gettop(vm);
+
+    if (nParams == 2) { // Need 1 (sic) params.
+        SQInteger i;
+
+        if (!SQ_FAILED(sq_getinteger(vm, 2, &i))) {
+            if (Interrupts::reserve()) {
+                pThis = new InterruptIn(vm, static_cast<PinName>(i));
+            } else {
+                printf("error: Out of memory.\n");
+            }
+        } else {
+            printf("error: Could not get integer.\n");
+        }
+    } else {
+        printf("error: nParams != 2\n");
+    }
+
+    return pThis;
+}
+
+}