<commit_before># Adel
**A new way to program microcontrollers**

**NOTE:** This code is under active development, so the API could still change. Also, please see usage warnings at the end of this document. 

Adel is a library that makes it easier to program microcontrollers, such as the Arduino. The main idea is to provide a simple kind of concurrency, similar to coroutines. Using Adel, any function can be made to behave in an asynchronous way, allowing it to run concurrently with other Adel functions without interfering with them. The library is implemented entirely as a set of C/C++ macros, so it requires no new compiler tools or flags. Just download the Adel directory and install it in your Arduino IDE libraries folder.

## Overview and examples

Adel came out of my frustration with microcontroller programming. In particular, that seemingly simple behavior can be very hard to implement. As an example, consider a function that blinks an LED attached to some pin every N milliseconds:

```{c++}
void blink(int some_pin, int N) {
   digitalWrite(some_pin, HIGH);
   delay(N);
   digitalWrite(some_pin, LOW);
   delay(N);
}
```

OK, that's easy enough. I can call it with two different values, say 500ms and 300ms:

```{c++}
for (int i = 0; i < 100; i++) blink(3, 500);
for (int i = 0; i < 100; i++) blink(4, 300);
```

But what if I want to blink them **at the same time**? Now, suddenly, I have lost composability. This code doesn't work:

```{c++}
for (int i = 0; i < 100; i++) {
  blink(3, 500);
  blink(4, 300);
}
```

To get **concurrent** behavior I have to write completely different code, which makes the scheduling explicit:

```{c++}
int last300, last500;
loop() {
  uint32_t t = millis();
  if (t - last300 > 300) {
    if (pin3_on) digitalWrite(3, LOW);
    else digitalWrite(3, HIGH);
    last300 = t;
  }
  if (t - last500 > 500) {
    ... etc ...
 }
 ```

Aside from the obvious complexity of this code, there are a couple of specific problems. First, all behaviors that might occur concurrently must be part of the same loop with the same timing control. The modularity is completely gone. Second, we need to introduce a global variable for each behavior that remembers the last time it executed. The code would become significantly more complex if we wanted to blink the lights for a specific amount of time, or if we had other modes where the lights are not blinking. Similar problems arise with input as well. Imagine if we want to blink a light until a button is pressed (inluding debouncing the button signal). 

The central problem is the `delay()` function, which makes timing easy for individual behaviors, but blocks the whole processor. The key feature of Adel, therefore, is an asynchronous delay function called `adelay` (hence the name Adel). The `adelay` function works just like `delay`, but allows other code to run concurrently. 

Concurrency in Adel is specified at the function granularity, using a fork-join style of parallelism. Functions are designated as "Adel functions" by defining them in a stylized way. The body of the function can use any of the Adel library routines shown below:

* `adelay( T )` : asynchronously delay the current function for T milliseconds.
* `andthen( f )` : run Adel function `f` to completion before continuing (synchronous execution).
* `await( c )` : wait asynchronously until condition `c` is true (`c` must *not* be an Adel function).
* `aforatmost( T, f )` : run Adel function `f` until it completes, or T milliseconds (whichever comes first)
* `atogether( f , g )` : run Adel functions `f` and `g` concurrently until they **both** finish.
* `auntil( f , g ) { ... } else { ... }` : run Adel functions `f` and `g` concurrently until **one** of them finishes. Executes the true branch if `f` finishes first or the false branch if `g` finishes first.
* `afinish` : finish executing the current function (like a return)
* `alternate( f , g )` : run `f` continuously until it yields by calling `ayourturn`; then run `g` until it yields. Continue back and forth until either function completes.
* `ayourturn( v )` : use in a function being called by `alternate` to yield control to the other function. The value `v` is made available to the other function.
* `amyturn` : gets the value passed through by `ayourturn`.

Using these routines we can rewrite the blink routine (below). Notice that I added a `while (1)` infinite loop -- this function will blink the light forever, or until it is stopped by its caller. *And that's ok* because it will not stop other code from running.

```{c++}
adel blink(int some_pin, int N) 
{
  abegin:
  while (1) {
    digitalWrite(some_pin, HIGH);
    adelay(N);
    digitalWrite(some_pin, LOW);
    adelay(N);
  }
  aend;
}
```

Every Adel function contains a minimum of three things: return type `adel`, and macros `abegin:` and `aend` at the begining and end of the function. (**NOTE** that ``abegin`` is always followed by a colon). But otherwise, the code is almost identical. The key feature is that we can execute blink concurrently, like this:

```{c++}
atogether( blink(3, 500), blink(4, 500) );
```
<commit_msg>Added aramp<commit_after># Adel
**A new way to program microcontrollers**

**NOTE:** This code is under active development, so the API could still change. Also, please see usage warnings at the end of this document. 

Adel is a library that makes it easier to program microcontrollers, such as the Arduino. The main idea is to provide a simple kind of concurrency, similar to coroutines. Using Adel, any function can be made to behave in an asynchronous way, allowing it to run concurrently with other Adel functions without interfering with them. The library is implemented entirely as a set of C/C++ macros, so it requires no new compiler tools or flags. Just download the Adel directory and install it in your Arduino IDE libraries folder.

## Overview and examples

Adel came out of my frustration with microcontroller programming. In particular, that seemingly simple behavior can be very hard to implement. As an example, consider a function that blinks an LED attached to some pin every N milliseconds:

```{c++}
void blink(int some_pin, int N) {
   digitalWrite(some_pin, HIGH);
   delay(N);
   digitalWrite(some_pin, LOW);
   delay(N);
}
```

OK, that's easy enough. I can call it with two different values, say 500ms and 300ms:

```{c++}
for (int i = 0; i < 100; i++) blink(3, 500);
for (int i = 0; i < 100; i++) blink(4, 300);
```

But what if I want to blink them **at the same time**? Now, suddenly, I have lost composability. This code doesn't work:

```{c++}
for (int i = 0; i < 100; i++) {
  blink(3, 500);
  blink(4, 300);
}
```

To get **concurrent** behavior I have to write completely different code, which makes the scheduling explicit:

```{c++}
int last300, last500;
loop() {
  uint32_t t = millis();
  if (t - last300 > 300) {
    if (pin3_on) digitalWrite(3, LOW);
    else digitalWrite(3, HIGH);
    last300 = t;
  }
  if (t - last500 > 500) {
    ... etc ...
 }
 ```

Aside from the obvious complexity of this code, there are a couple of specific problems. First, all behaviors that might occur concurrently must be part of the same loop with the same timing control. The modularity is completely gone. Second, we need to introduce a global variable for each behavior that remembers the last time it executed. The code would become significantly more complex if we wanted to blink the lights for a specific amount of time, or if we had other modes where the lights are not blinking. Similar problems arise with input as well. Imagine if we want to blink a light until a button is pressed (inluding debouncing the button signal). 

The central problem is the `delay()` function, which makes timing easy for individual behaviors, but blocks the whole processor. The key feature of Adel, therefore, is an asynchronous delay function called `adelay` (hence the name Adel). The `adelay` function works just like `delay`, but allows other code to run concurrently. 

Concurrency in Adel is specified at the function granularity, using a fork-join style of parallelism. Functions are designated as "Adel functions" by defining them in a stylized way. The body of the function can use any of the Adel library routines shown below:

* `adelay( T )` : asynchronously delay the current function for T milliseconds.
* `andthen( f )` : run Adel function `f` to completion before continuing (synchronous execution).
* `await( c )` : wait asynchronously until condition `c` is true (`c` must *not* be an Adel function).
* `aforatmost( T, f )` : run Adel function `f` until it completes, or T milliseconds (whichever comes first)
* `atogether( f , g )` : run Adel functions `f` and `g` concurrently until they **both** finish.
* `auntil( f , g ) { ... } else { ... }` : run Adel functions `f` and `g` concurrently until **one** of them finishes. Executes the true branch if `f` finishes first or the false branch if `g` finishes first.
* `aramp( T, v, min, max) { ... }` : execute the body for T milliseconds; each time it is executed, v will be set to a value between min and max proportional to the fraction of T that has elapsed. Useful for turning something on or off over a specific period of time.
* `afinish` : finish executing the current function (like a return)
* `alternate( f , g )` : run `f` continuously until it yields by calling `ayourturn`; then run `g` until it yields. Continue back and forth until either function completes.
* `ayourturn( v )` : use in a function being called by `alternate` to yield control to the other function. The value `v` is made available to the other function.
* `amyturn` : gets the value passed through by `ayourturn`.

Using these routines we can rewrite the blink routine (below). Notice that I added a `while (1)` infinite loop -- this function will blink the light forever, or until it is stopped by its caller. *And that's ok* because it will not stop other code from running.

```{c++}
adel blink(int some_pin, int N) 
{
  abegin:
  while (1) {
    digitalWrite(some_pin, HIGH);
    adelay(N);
    digitalWrite(some_pin, LOW);
    adelay(N);
  }
  aend;
}
```

Every Adel function contains a minimum of three things: return type `adel`, and macros `abegin:` and `aend` at the begining and end of the function. (**NOTE** that ``abegin`` is always followed by a colon). But otherwise, the code is almost identical. The key feature is that we can execute blink concurrently, like this:

```{c++}
atogether( blink(3, 500), blink(4, 500) );
```

{'fraction_non_alphanumeric': 0.09009863429438543, 'fraction_numerical': 0.013277693474962063, 'mean_word_length': 4.101596516690856, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2155671', 'n_tokens_mistral': 3126, 'n_tokens_neox': 2882, 'n_words': 1616}