aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/external/protothreads/pt-1.4/example-codelock.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/external/protothreads/pt-1.4/example-codelock.c')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/external/protothreads/pt-1.4/example-codelock.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/external/protothreads/pt-1.4/example-codelock.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/protothreads/pt-1.4/example-codelock.c
new file mode 100644
index 0000000..cbeeb96
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/external/protothreads/pt-1.4/example-codelock.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: example-codelock.c,v 1.5 2005/10/06 07:57:08 adam Exp $
+ */
+
+/*
+ *
+ * This example shows how to implement a simple code lock. The code
+ * lock waits for key presses from a numeric keyboard and if the
+ * correct code is entered, the lock is unlocked. There is a maximum
+ * time of one second between each key press, and after the correct
+ * code has been entered, no more keys must be pressed for 0.5 seconds
+ * before the lock is opened.
+ *
+ * This is an example that shows two things:
+ * - how to implement a code lock key input mechanism, and
+ * - how to implement a sequential timed routine.
+ *
+ * The program consists of two protothreads, one that implements the
+ * code lock reader and one that implements simulated keyboard input.
+ *
+ *
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+
+#include "pt.h"
+
+/*---------------------------------------------------------------------------*/
+/*
+ * The following definitions are just for the simple timer library
+ * used in this example. The actual implementation of the functions
+ * can be found at the end of this file.
+ */
+struct timer { int start, interval; };
+static int timer_expired(struct timer *t);
+static void timer_set(struct timer *t, int usecs);
+/*---------------------------------------------------------------------------*/
+/*
+ * This example uses two timers: one for the code lock protothread and
+ * one for the simulated key input protothread.
+ */
+static struct timer codelock_timer, input_timer;
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the code that has to be entered.
+ */
+static const char code[4] = {'1', '4', '2', '3'};
+/*---------------------------------------------------------------------------*/
+/*
+ * This example has two protothread and therefor has two protothread
+ * control structures of type struct pt. These are initialized with
+ * PT_INIT() in the main() function below.
+ */
+static struct pt codelock_pt, input_pt;
+/*---------------------------------------------------------------------------*/
+/*
+ * The following code implements a simple key input. Input is made
+ * with the press_key() function, and the function key_pressed()
+ * checks if a key has been pressed. The variable "key" holds the
+ * latest key that was pressed. The variable "key_pressed_flag" is set
+ * when a key is pressed and cleared when a key press is checked.
+ */
+static char key, key_pressed_flag;
+
+static void
+press_key(char k)
+{
+ printf("--- Key '%c' pressed\n", k);
+ key = k;
+ key_pressed_flag = 1;
+}
+
+static int
+key_pressed(void)
+{
+ if(key_pressed_flag != 0) {
+ key_pressed_flag = 0;
+ return 1;
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Declaration of the protothread function implementing the code lock
+ * logic. The protothread function is declared using the PT_THREAD()
+ * macro. The function is declared with the "static" keyword since it
+ * is local to this file. The name of the function is codelock_thread
+ * and it takes one argument, pt, of the type struct pt.
+ *
+ */
+static
+PT_THREAD(codelock_thread(struct pt *pt))
+{
+ /* This is a local variable that holds the number of keys that have
+ * been pressed. Note that it is declared with the "static" keyword
+ * to make sure that the variable is *not* allocated on the stack.
+ */
+ static int keys;
+
+ /*
+ * Declare the beginning of the protothread.
+ */
+ PT_BEGIN(pt);
+
+ /*
+ * We'll let the protothread loop until the protothread is
+ * expliticly exited with PT_EXIT().
+ */
+ while(1) {
+
+ /*
+ * We'll be reading key presses until we get the right amount of
+ * correct keys.
+ */
+ for(keys = 0; keys < sizeof(code); ++keys) {
+
+ /*
+ * If we haven't gotten any keypresses, we'll simply wait for one.
+ */
+ if(keys == 0) {
+
+ /*
+ * The PT_WAIT_UNTIL() function will block until the condition
+ * key_pressed() is true.
+ */
+ PT_WAIT_UNTIL(pt, key_pressed());
+ } else {
+
+ /*
+ * If the "key" variable was larger than zero, we have already
+ * gotten at least one correct key press. If so, we'll not
+ * only wait for the next key, but we'll also set a timer that
+ * expires in one second. This gives the person pressing the
+ * keys one second to press the next key in the code.
+ */
+ timer_set(&codelock_timer, 1000);
+
+ /*
+ * The following statement shows how complex blocking
+ * conditions can be easily expressed with protothreads and
+ * the PT_WAIT_UNTIL() function.
+ */
+ PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
+
+ /*
+ * If the timer expired, we should break out of the for() loop
+ * and start reading keys from the beginning of the while(1)
+ * loop instead.
+ */
+ if(timer_expired(&codelock_timer)) {
+ printf("Code lock timer expired.\n");
+
+ /*
+ * Break out from the for() loop and start from the
+ * beginning of the while(1) loop.
+ */
+ break;
+ }
+ }
+
+ /*
+ * Check if the pressed key was correct.
+ */
+ if(key != code[keys]) {
+ printf("Incorrect key '%c' found\n", key);
+ /*
+ * Break out of the for() loop since the key was incorrect.
+ */
+ break;
+ } else {
+ printf("Correct key '%c' found\n", key);
+ }
+ }
+
+ /*
+ * Check if we have gotten all keys.
+ */
+ if(keys == sizeof(code)) {
+ printf("Correct code entered, waiting for 500 ms before unlocking.\n");
+
+ /*
+ * Ok, we got the correct code. But to make sure that the code
+ * was not just a fluke of luck by an intruder, but the correct
+ * code entered by a person that knows the correct code, we'll
+ * wait for half a second before opening the lock. If another
+ * key is pressed during this time, we'll assume that it was a
+ * fluke of luck that the correct code was entered the first
+ * time.
+ */
+ timer_set(&codelock_timer, 500);
+ PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
+
+ /*
+ * If we continued from the PT_WAIT_UNTIL() statement without
+ * the timer expired, we don't open the lock.
+ */
+ if(!timer_expired(&codelock_timer)) {
+ printf("Key pressed during final wait, code lock locked again.\n");
+ } else {
+
+ /*
+ * If the timer expired, we'll open the lock and exit from the
+ * protothread.
+ */
+ printf("Code lock unlocked.\n");
+ PT_EXIT(pt);
+ }
+ }
+ }
+
+ /*
+ * Finally, we'll mark the end of the protothread.
+ */
+ PT_END(pt);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the second protothread in this example. It implements a
+ * simulated user pressing the keys. This illustrates how a linear
+ * sequence of timed instructions can be implemented with
+ * protothreads.
+ */
+static
+PT_THREAD(input_thread(struct pt *pt))
+{
+ PT_BEGIN(pt);
+
+ printf("Waiting 1 second before entering first key.\n");
+
+ timer_set(&input_timer, 1000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 2000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 2000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 1500);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 300);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 400);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 500);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 2000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ PT_END(pt);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the main function. It initializes the two protothread
+ * control structures and schedules the two protothreads. The main
+ * function returns when the protothread the runs the code lock exits.
+ */
+int
+main(void)
+{
+ /*
+ * Initialize the two protothread control structures.
+ */
+ PT_INIT(&input_pt);
+ PT_INIT(&codelock_pt);
+
+ /*
+ * Schedule the two protothreads until the codelock_thread() exits.
+ */
+ while(PT_SCHEDULE(codelock_thread(&codelock_pt))) {
+ PT_SCHEDULE(input_thread(&input_pt));
+
+ /*
+ * When running this example on a multitasking system, we must
+ * give other processes a chance to run too and therefore we call
+ * usleep() resp. Sleep() here. On a dedicated embedded system,
+ * we usually do not need to do this.
+ */
+#ifdef _WIN32
+ Sleep(0);
+#else
+ usleep(10);
+#endif
+ }
+
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Finally, the implementation of the simple timer library follows.
+ */
+#ifdef _WIN32
+
+static int clock_time(void)
+{ return (int)GetTickCount(); }
+
+#else /* _WIN32 */
+
+static int clock_time(void)
+{
+ struct timeval tv;
+ struct timezone tz;
+ gettimeofday(&tv, &tz);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+#endif /* _WIN32 */
+
+static int timer_expired(struct timer *t)
+{ return (int)(clock_time() - t->start) >= (int)t->interval; }
+
+static void timer_set(struct timer *t, int interval)
+{ t->interval = interval; t->start = clock_time(); }
+/*---------------------------------------------------------------------------*/