Examples

Hello Zerynth

Hello World
============

The simplest example to be tried for starting with embedded development  

tags: [First Steps, Serial]
groups:[First Steps]
###############################################################################
# Hello Zerynth
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

# import the streams module, it is needed to send data around
import streams

# open the default serial port, the output will be visible in the serial console
streams.serial()  

# loop forever
while True:
    print("Hello Zerynth!")   # print automatically knows where to print!
    sleep(1000)

Digital Read

Digital Read Basics 
==================================================

The basic definition of digitalRead() in ZERYNTH has the same behaviour of Arduino digitalRead().

In this example simple digitalRead use is reported

tags: [First Steps,Digital Read ADC]
groups:[First Steps]  
################################################################################
# Digital Read Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port stream with default parameters  
streams.serial()

# configure pin D5 in input mode
pinMode(D5, INPUT_PULLUP)

# loop forever, printing the value of D5
while True:
    print(digitalRead(D5))
    sleep(500)  

Analog To Digital Acquisition

ADC Analog to Digital Acquisition Basics 
==================================================

The function for Analog to Digital convertion in ZERYNTH is adc.read()

The complete definition is adc.read(pin, samples=1) 

In this example simple ADC single pin acquisition and advanced multi sample ADC acquisition are reported.

In ZERYNTH ADC is also available as builtin analogRead() with the same signature of adc.read(). analogRead() is available only for compatibility with the Arduino world and will be deprecated in future versions of ZERYNTH.

tags: [First Steps,Analog Read ADC]
groups:[First Steps]
################################################################################
# Analog Read
# 
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams  # import the streams module
import adc      # import the adc driver 

# create a stream linked to the default serial port
streams.serial() 

while True:
    
# Basic usage of ADC for acquiring the analog signal from a pin   
    value = adc.read(A0)
    print("One sample:",value)

# The complete definition of adc.read() is adc.read(pin, samples=1) 
# For an advanced usage of adc.read refer to the official Zerynth documentation

#acquire 10 samples with default sampling period    
    value2 = adc.read(A0,10)
    print("10 samples:\n",value2)
    
#acquire 3 samples from the first 4 analog pins of the board with default sampling period    
    value3= adc.read([A0,A1,A2,A3],3)
    print("3 samples from A0, A1, A2 and A3:\n",value3)

    print()
    sleep(300)

Analog To Digital Voltage Conversion

ADC Analog to Digital Acquisition with Voltage Conversion
=========================================================
This basic examples shows how to read an analog voltage from pin 0, converts it to the corresponding voltage, and prints the result to the serial monitor.
To test it user can attach the center pin of a potentiometer to pin A0, and the other pins respectively to to +3.3V and GND.

tags: [Analog Read ADC, Sensors, First Steps]  
groups:[First Steps]
################################################################################
# Analog Read to Voltage
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import adc      # import the adc module  

#create a serial port stream with default parameters
streams.serial()

#define the analog pin for reading the value 
inputAnalog = A0

#set the pin as input with INPUT_ANALOG,
pinMode(inputAnalog,INPUT_ANALOG)

while True:
       
    #read the input on analog pin 0
    sensorValue = adc.read(inputAnalog)
    
    #convert the analog reading (which goes from 0 - 4095.0) to a voltage (0 - 3.3V):
    voltage = sensorValue * (3.3 / 4095.0)
    
    #print out the raw and converted values:
    print("sensor raw value:", sensorValue,"Voltage:",voltage)
    
    sleep(300)


Oscilloscope

ZERYNTH Oscilloscope
======================
Simple usage of the analog acquisition and of the Python smart print functions.
The example shows how to print to the serial console the values read on an analog pin in a "scope" like graphicspretty way.


tags: [First Steps, Analog Read ADC, Serial]
groups:[First Steps]     
###############################################################################
# Zerynth oscilloscope
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

import streams
import adc
   
streams.serial()

while True:
    value = adc.read(A4)
    conv = value*80//4095
    print("|","#"*conv," "*(80-conv),"|")
    sleep(200)
    

Serial Port Read-Write Basics

Serial Port Read/Write Basics
==============================

Basic examples of read and write data through a serial port.
In this example a serial port instance is created allowing use of various methods.

tags:[Serial, First Steps]
groups:[First Steps]   
################################################################################
# Serial Port Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
# creates a serial port and name it "s"
s=streams.serial()

while True:
    print("Write some chars on the serial port and terminate with \\n (new line)")
    line=s.readline() # read and return any single character available on the serial port until a \n is found
    print("You wrote:", line)
    print()
    sleep (300)
      
    
   

Multi Thread Basic

Multi-Thread Basics
=====================

This examples shows the basics of ZERYNTH multi-threading
In ZERYNTH a thread require a function to be executed as input for the definition
the same function can be instanced by various thread giving you the possibility to write very concise and readable code.
In this example 4 threads are created as instances of the same function where different parameters are passed to the function when the thread is initialized

Note that the while True main loop typical of imperative programming is not present in this code. ZERYNTH allows pure thread driven implementation!

tags: [First Steps, Multi-Thread]   
groups:[First Steps]
################################################################################
# Multi-Thread Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port with default parameters
streams.serial()

# Define a function to be used in the various threads.
# Parameters are passed to the function when the thread is created and then used in the thread loop.
# To be continuously executed by a thread a function requires an infinite loop,
# otherwise when the function terminates the thread is closed
     
def threadfn(number,delay):    
    
    while True:                    
        print("I am the thread",number)
        print("I run every:",delay,"msec")
        print()                # just add an empty line for console output readability 
        sleep(delay)

# create the various threads using the same function but passing different parameters        
thread(threadfn,1,500)
thread(threadfn,2,1000)
thread(threadfn,3,1300)
thread(threadfn,4,800)
   

Serial Port Read-Write Advanced

Serial Port Advanced
=====================

Advanced example of using a serial port for writing and sending data
The examples shows how to read the entire serial port buffer or how to read a defined number of chars from the buffer.
Moreover is also shown how to read a buffer until a \n newline terminator is found.

tags:[Serial, First Steps]
groups:[First Steps]
################################################################################
# Serial Advanced
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

s = streams.serial()

# Testing various serial port reading methods
   
while True:
    print("write some chars and send it to the board")
    char=s.read() # read and return any single character available on the serial port one by one
    print("This is the first char you wrote:",char)
    print() # add a line space for improving the serial console ouput readability
    
    sleep(500) # waiting for the serial buffer to fill
    length=s.available() # check if data are available on the port and count them
    chars=s.read(length) # read all the bytes available in the buffer an return the bytearray 
    print("This are the other", length, "chars you wrote:",chars)
    print() # add a line space for improving the serial console view
    
    print("write a line ending it with return or enter")
    line=s.readline() # read until a line terminator \n is found, then return a bytearray
    print("This is the line you wrote:",line)

Input Capture Unit

Input Capture Unit as PWM Analyzer
===================================

This examples shows how to use the Input Capture Unit of the board MCU for analysing a PWM signal 
The PWM is generated on PIN13 in order to have a feedbakc on the board embedded LED
PIN13 is also connected through a wire with PIN2 on which the ICU capture is activated
An interrupt is also attached on a PIN where a button is connected for changing the PWM duty.

Very Important: ICU and PWM are both timer powered embedded feature, it is impossible to run an ICU and a PWM
on two pin controlled by the same timer channel. 
Please refer to the board pinout in order to select the proper pins for your board
e.i: on a ST Nucleo this example use PWM2/1 for PIN13 and PWM1/3 for PIN2 so we are using two diferent embedded timers (first number on the PEM pin descrition)

Board setup:   
  PIN13-----PIN2  (shortcut the pins)
  BTNPin----GND   (connect a button between a pin and GND)  

tags: [First Steps, Input Capture Unit ICU, Interrupts, Analog Write PWM]  
groups:[First Steps]


################################################################################
# Input Capture Unit as PWM Analyzer
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import pwm 
import icu
import streams

# create the serial port using default parameters  
streams.serial()

# define a pin where a button is connected, you can use the Nucleo button pin as input or change it with any other digital pin available

# this is the pin the button is connected to; for the various supported boards, Zerynth automatically translates it 
# to the board button. On Arduino DUE the user button isn't installed, so this line rises a compilation error.
# On Arduino DUE, change it to the pin your button is connected to or comment this line (see below)
buttonPin=BTN0


# define the ICU pin. D5 works with Arduino footprint boards while with Particle boards D0 can be used 
captPin=D5.ICU  # On Arduino like boards
#captPin=D0.ICU  # On Particle boards

# define the PWM pin. D13 works with Arduino footprint boards (and is also connected to a LED) while with Particle boards A4 can be used
pwmPin=D13.PWM # On Arduino like boards 
#pwmPin=A4.PWM # On Particle boards

# set the pin as input with PullUp, the button will be connected to ground
pinMode(buttonPin, INPUT_PULLUP)

# define a function for printing capture results on the serial port
def print_results(y):
    print("Time ON is:", y[0],"micros")
    print("Time OFF is:",y[1],"micros")
    print("Period is:", y[0]+y[1], "micros")
    print()
    
# define a global variable for PWM duty cycle and turn on the PWM

duty=10
pwm.write(pwmPin,100, duty,MICROS) #pwm.write needs (pn, period, duty, time_unit)

# define the function to be called for changing the PWM duty when the button is pressed
def pwm_control():
    global duty
    duty= duty+10
    if duty>=100:
        duty=0
    pwm.write(pwmPin, 100, duty,MICROS)
    print("Duty:", duty, "millis")
    
# Attach an interrupt on the button pin waiting for signal going from high to low when the button is pressed.
# pwm_control will be called when the interrupt is fired.
# If you are on Arduino DUE and you haven't connected any button comment the following line 
# you will not change the PWM duty but you can still test the ICU capture
onPinFall(buttonPin, pwm_control)

while True:
    # start an icu capture to be triggered when the pin rise.
    # this routine acquires 10 steps (HIGH or LOW states) or terminates after 50000 micros
    # this is a blocking function
    x = icu.capture(captPin,LOW_TO_HIGH,10,50000,MICROS)
    print("captured")
    # x is a list of step durations in microseconds, pass it to the printing function and check the serial console
    print_results(x)
    
    sleep(1000)
    

Timers Basics

Timers Basics
==============

Basic example of use of the timer module for monitoring the time during the program execution.
Timers can be used as alternative to the Arduino Millis().


tags=[First Steps, Timers]
groups:[First Steps]    
################################################################################
# Timers Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import timers
import streams

# create a serial port with default parameters
streams.serial()

# create a new timer
t=timers.timer()
# start the timer
t.start()

minutes=0
   
while True:
    
    if t.get()>= 60000:        #check if 60 seconds are passed
        t.reset()              #timer can be reset
        minutes +=1
    seconds=t.get()//1000
    print("time is:", minutes,":",seconds) #just print the current value since timer start or last reset
    print("System time is:", timers.now(), "(millis)") #timers.now() gives the system time in milliseconds since program start
    print()
    
    sleep(500)                 #run every 500 millisec

Strings Format

String Formatting
=================

Some example of Python string formatting with the modulo operator.
################################################################################
# strformat
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

streams.serial()

print("Starting!")
sleep(1000)

# a data tuple
tt = ("string",-21,15.23,32)
# a data dictionary
dd = {
      "thing":"string",
      "number":1,
      "float":1.0,
      "hex":32  
}

# let's format :)
while True:
    try:
        # basic formatting
        print("%% this is a %s, this is a %d, this is a %f, this is a %x, this is a %%"%tt)
        # named keys formatting
        print("%% this is a %(thing)s, this is a %(number)d, this is a %(float)f, this is a %(hex)x, this is a %%"%dd)
        # width & precision
        print("%s %8d %f %d"%tt)
        print("%s %08.7d %f %d"%tt)
        # width & precision & left alignment & sign
        print("%s %-010.9d %f %d"%tt)
        print("%s %-010.9d %2.0f %d"%tt)
        print("%s %-010.9d %2.5f %d"%tt)
        print("%s %-010.9d %12.5f %d"%tt)
        print("%s %-010.9d %-12.5f %d"%tt)
        print("%s %-010.9d %012.15f %d"%tt)
        print("%s %+010.9d %012.15f %d"%tt)
        print("%s % 010.9d %012.15f %d"%tt)
        # width & precision for strings
        print("%15.3s % 010.9d %012.15f %d"%tt)
        # variable width & precision
        print("%x %3.*d"%(123456,5,6))
    except Exception as e:
        print(e)
    sleep(5000)

Dac Basic

DAC Basic
=========

A simple example to introduce Dac features.
################################################################################
# Dac Basic
#
# Created by Zerynth Team 2015 CC
# Authors: L. Rizzello
################################################################################

import streams
import adc # for analogRead

import dac


def readInput():
    while True:
        print("reading A1: ",analogRead(A1))
        sleep(500)

streams.serial()
pinMode(A1,INPUT)

# read input in a separate thread
thread(readInput)

my_dac = dac.DAC(D8.DAC)
my_dac.start()

# circular mode: continuously repeat the input buffer
my_dac.write([100,200,900,800],1000,MILLIS,circular=True)

Buzzer with PWM

Buzzer Driven through PWM
==========================
This example shows how to drive a buzzer using PWM. 
In the example a frequency ramp going from 100 Hz to 5 KHz is generated as drive.
The frequency is converted in period to be used as input of the pwm.rite function that require period and pulse to be expressed in milli or micro seconds (measure unit can be selected as extra parameter of the pwm.write function).
The PWM duty cycle is set to 50% driving the buzzer with a symmetric square wave. 

tags:[First Steps, Input Capture Unit ICU, Sound]  
groups:[First Steps]


################################################################################
# Buzzer with PWM
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import pwm

#create a serial port stream with default parameters  
streams.serial()

# the pin where the buzzer is attached to
buzzerpin = D8.PWM 

pinMode(buzzerpin,OUTPUT) #set buzzerpin to output mode
frequency=100             #define a variable to hold the played tone frequency

while True:
    period=1000000//frequency #we are using MICROS so every sec is 1000000 of micros. // is the int division, pwm.write period doesn't accept floats
    print("frequency is", frequency,"Hz")
    
    #set the period of the buzzer and the duty to 50% of the period
    pwm.write(buzzerpin,period,period//2,MICROS)
        
    # increment the frequency every loop
    frequency = frequency + 20 
        
    # reset period
    if frequency >= 5000:
        frequency=100
        
    sleep(100) 

PWM Fade

LED Fade
========

This example shows hot to use PWM for fading a LED by changing the duty cycle in a for loop.


################################################################################
# LED Fade
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi,  D. Mazzei
###############################################################################

import pwm

duty=0

pinMode(LED0,OUTPUT) # set the LED pin as output:

while True:
    for i in range(-100,100,1):   # create a loop for ranging the duty cycle from 0 to 100 MICROS
        duty=100-abs(i)
        pwm.write(LED0.PWM,100,duty,MICROS)     # set the pwm at the calculated duty with a fixed period of 100 MICROS
        sleep(10) # update the PWM every 10 millis  

InfraRed Raw Capture

ICU Capture IR Packets
=======================
Basic example of use of the ICU feature for capturing IR signals acquired through an IR demodulator.



################################################################################
# ICU Capture IR Packets
#
# Created by Zerynth Team 2015 CC
# Authors: L. Rizzello, G. Baldi, D. Mazzei  
################################################################################

import icu
import streams
import pwm

streams.serial()

# Set the pin the IR receiver is connected to.
# In this example D2 is used: if you happen to have a TOI Shield on an Arduino compatible board
# you are good to go.
ir_pin = D2.ICU # when you want to use a particular pin function, just use the dot notation


def IR_capture():
    while True:
        print("Capturing...")
        # Starts capturing from the icu configured pin.
        # The capture starts from a selected trigger (in this case capture will start when the pin first goes from
        # HIGH to LOW).
        # The max number of samples to be collected and a maximum time window are specified.
        
        # Play with max number and time window to fit your remote protocol.
        # The following values are for the NEC IR (used by LG) protocol
        x = icu.capture(ir_pin,LOW,67,68,pull=HIGH)
        print(x,"\n captured n samples:",len(x))
               
    
# captures in a different thread
thread(IR_capture)

while True:
    print("alive!")
    sleep(1000)

Timers Advanced

Timers Advanced Use
======================

This example shows how ZERYNTH soft timers can be used to schedule functions execution.
ZERYNTH timers can be used as program time counter through the timer.start attribute or as recursive callers through the timer.interval method that takes as input the elapsing interval and the function to be called.
Moreover, it is also possible to activate a timer in one shot mode. In this case the function si called after the requested interval and then the timer stops

tags: [Timers, First Steps]  
groups:[First Steps]    




################################################################################
# Timers Advanced Use

# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import timers
import streams

# create a serial port with default parameters
streams.serial()

# create new timers
tsec=timers.timer()
tminute=timers.timer()     
tshoot=timers.timer()

seconds=0
minutes=0

# define a function to call when the timer for seconds elapses
def secondpassed():
    global seconds
    seconds +=1
    print(seconds,"  seconds")
    if seconds==60:
        seconds=0

# define a function to call when the timer for minutes elapses
def minutepassed():
    global minutes
    minutes +=1
    print(minutes,"  minutes")
    
# define a function to call when the one shot timer elapses
def shootpassed():
    print("1 second ago was 1:30")
    
# start the timers for minutes and seconds
tsec.interval(1000,secondpassed)
tminute.interval(60000,minutepassed)
tsec.start()
tminute.start()
    
while True:
    
    if seconds==30 and minutes==1:                               # do a check on passed time to trigger a oneshot timer 
        tshoot.one_shot(1000, shootpassed)                       # this is a oneshot timer, it executes only one time
                
    print("timer minutes runs since:", tminute.get(),"timer seconds runs since:",tsec.get(), "millisec")         #just print the current value since start or last reset
    sleep(2500)                 #run every 2500 millisec

Queues

Queues
======

Simple producer/consumer example based on thread safe queues.
################################################################################
# Queues
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import threading
import streams
import queue


streams.serial()

# create a bounded queue
q = queue.Queue(maxsize=20)

# keep producing an element every 100 millis
def producer(id):
    while True:
        try:
            x = random(0,100)
            print("producer",id,"->",x)
            q.put(x)
        except Exception as e:
            print(e)
        sleep(100)

# keep consuming an element every 1 second
def consumer(id):
    while True:
        try:
            print("consumer",id,"<-",q.get())
        except Exception as e:
            print(e)
        sleep(1000)

# start everyone
thread(producer,0)
thread(consumer,1)
thread(consumer,2)

while True:
    isfull = q.full()
    print("Queue is full?",isfull)
    if isfull:
        # clear queue if full
        print("Clearing queue")
        q.clear()
    sleep(5000)

Interrupts

Interrupt Basics
===================

This example shows how to use interrupts for monitoring pin state changes.
A button is used to connect a pin to ground when pressed. The pin is set as INPUT_PULLUP putting HIGH voltage on it while activated as digital input.
It is possible to use onboard embedded button like in the case of ST Nucleo.
Otherwise an external button can be connected to any digital pin available on the board and then to GND. In this case the pin number have to be changed with the pin used for connecting the button

Note that the main loop (while True) is not present in this example. With ZERYNTH it is possible to write pure event driven code!

tags: [First Steps, Interrupts, Digital I/O]
groups:[First Steps]  
################################################################################
# Interrupt Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port stream with default parameters
streams.serial()

# define where the button and the LED are connected
# in this case BTN0 will be automatically configured according to the selected board button
# change this definition to connect external buttons on any other digital pin
buttonPin=BTN0 
ledPin=LED0  # LED0 will be configured to the selected board led

# configure the pin behaviour to drive the LED and to read from the button  
pinMode(buttonPin,INPUT_PULLUP)
pinMode(ledPin,OUTPUT)

# define the function to be called when the button is pressed
def pressed():
        print("touched!")
        digitalWrite(ledPin,HIGH) # just blink the LED for 100 millisec when the button is pressed
        sleep(100)
        digitalWrite(ledPin,LOW)

# attach an interrupt on the button pin and call the pressed function when it falls
# being BTN0 configured as pullup, when the button is pressed the signal goes to from HIGH to LOW.
# opposite behaviour can be obtained with the equivalent "rise" interrupt function: onPinRise(pin,fun)
# hint: onPinFall and onPinRise can be used together on the same pin, even with different functions
onPinFall(buttonPin,pressed)



Interrupts Debounce

Interrupt Advanced
===================

This example uses pwm to show the advanced feature of interrupt debouncing.
PWM triggers fall and rise events at different speeds, but interrupts are triggered only if the debounce time (i.e. the stable time after and event) is in the correct range.
################################################################################
# Interrupt Debounce
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# import streams
import streams
# import pwm for testing
import pwm


# CONNECT pin D3 to PIN D2 for this example to work!

streams.serial()

def on_touch_up():
    print("touched UP")

def on_touch_dn():
    print("touched DN")
    

    
try:    
    # D2 will call touch_up on rise and touch_dn on fall with different debounce times
    onPinRise(D2,on_touch_up,debounce=500)
    onPinFall(D2,on_touch_dn,debounce=300)
except Exception as e:
    print(e)




while True:
    for x in [100,200,300,400,500,600,700,800,900]:
        print("--->",x, 1000-x)
        # start pwm on D3 with the current period
        pwm.write(D3.PWM,1000,x)
        # now wait and check if debounce is working
        sleep(5000)

Exceptions-Debugger

Exceptions-Debugger Basic
=============================

Basic example of how to use the ZERYNTH Exceptions class to monitor and analyze programs behavior without crashing the execution.
The examples shows how a "division by zero" is identified in the code without causing any crash.
In ZERYNTH exceptions reported on the IDE serial console can be opened and analyzed through the integrated debugger window.

tags:[First Steps, Exceptions]
groups:[First Steps]  
################################################################################
# Exception-Debugger Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi,  D. Mazzei
###############################################################################

import streams

streams.serial()

while True:
    for x in range(-10,10,1):   # create a loop ranging on the integers between -10 and 10
        
        try:                    # open the Exception monitoring scope
            value=100//x        # when x=0 this will results in a DivisionByZero!
            print(value)
        except Exception as e:  # capture any raised exception as e
            print(e)            # print the content of e to monitor where the program is faulting
                                # click on the console X icon to open the Zerynth debugger window 
        sleep(1000)    
      

Math

===========
Math Module
===========

Some fun with math functions
###############################################################################
# Math module
#
# Created by Zerynth Team 2017 CC
# Authors: G. Baldi
###############################################################################
import streams
import math 

streams.serial()


while True:
    # loop over angles in degrees
    print("---> TRIGONOMETRY!")
    for angle in range(0,360*3,10):
        # convert to radians
        r = math.radians(angle)
        # take the sin
        s = math.sin(r)
        # calculate offset...
        sl = int(40*s)
        # ...and print!
        if sl>=0:
            print(" "*40,"#"*sl)
        else:
            print(" "*(40+sl),"#"*(-sl))
        sleep(50)
    sleep(1000)

    # loop from -5 to 0 in 0.05 increments
    print("---> EXPONENTIALS")
    x = -5
    incr = 0.05
    while x<0:
        # take the exp...
        y = math.exp(x)
        # ...and print!
        print("#"*int(y*80))
        # do not forget to increment x
        x = x + incr
        sleep(50)
    sleep(1000)
    
    print("---> ROOTS and POWERS")
    # loop from 1 to 100
    print(" a   |  b   |  c   | math.sqrt(a*a*+b*b)")
    print("----------------------------------------")
    for i in range(0,100):
        # let's generate and test Pythagorean Triples!
        # select n and m
        m = 1
        n = 0
        while m>=n:
            n = random(1,30)
            m = random(1,30)
        
        a = math.pow(n,2)-math.pow(m,2)
        b = 2*m*n 
        c = math.pow(n,2)+math.pow(m,2)
        a2 = math.pow(a,2)
        b2 = math.pow(b,2)
        p = math.sqrt(a2+b2)
        
        print("%4.0f | %4.0f | %4.0f | %4.0f"%(a,b,c,p))
        sleep(100)
    sleep(1000)

Mini Web Server

Mini Web Server
===============

This example implements a very minimal web server by opening a TCP socket
in listening mode, reading HTTP headers and sending out some HTML.

It prints the IP to connect to in the serial console. Type it in your browser
and test your mini web server!

It uses the CC3000 wireless driver, however any network driver can be used
changing only a few lines of code.


###############################################################################
# Mini Web Server
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

# import streams & socket
import streams
import socket

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# FOR THIS EXAMPLE TO WORK, A NETWORK DRIVER MUST BE SELECTED BELOW

# uncomment the following line to use the CC3000 driver (Particle Core or CC3000 Wifi shields)
# from texas.cc3000 import cc3000 as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()
# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# Yes! we are connected
print("Linked!")

# Let's print our ip, it will be needed soon
info = wifi.link_info()
print("My IP is:",info[0])

# Now let's create a socket and listen for incoming connections on port 80
sock = socket.socket()
sock.bind(80)
sock.listen()


while True:
    try:
        # Type in your browser the board ip!
        print("Waiting for connection...")
        # here we wait for a connection
        clientsock,addr = sock.accept()
        print("Incoming connection from",addr)
        
        # yes! a connection is ready to use
        # first let's create a SocketStream
        # it's like a serial stream, but with a socket underneath.
        # This way we can read and print to the socket
        client = streams.SocketStream(clientsock)
        
        # let's read all the HTTP headers from the browser
        # stop when a blank line is received
        line = client.readline()
        while line!="\n" and line!="\r\n":
            line = client.readline()
        print("HTTP request received!")
        
        # let's now send our headers (very minimal)
        # hint: \n is added by print
        print("HTTP/1.1 200 OK\r",stream=client)
        print("Content-Type: text/html\r",stream=client)
        print("Connection: close\r\n\r",stream=client)
        # see? as easy as print!
        print("<html><body>Hello Zerynth!",random(0,100),"</body></html>",stream=client)
        # close connection and go waiting for another one
        client.close()
    except Exception as e:
        print("ooops, something wrong:",e)

UDP Pinger

ZERYNTH UDP pinger
===================

This example demonstrates the use of UDP sockets. A writer thread sends UDP broadcast packets while a reader
threads catches them. Uplink this script on more than one board for some pinger fun!
################################################################################
# Zerynth UDP pinger
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# import streams & socket
import streams
import socket

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# FOR THIS EXAMPLE TO WORK, A NETWORK DRIVER MUST BE SELECTED BELOW

# uncomment the following line to use the CC3000 driver (Particle Core or CC3000 Wifi shields)
# from texas.cc3000 import cc3000 as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
    # get our ip
    myip = wifi.link_info()[0]
    # convert myip to a tuple with the socket.ip_to_tuple function
    # "x.y.z.w" becomes (x,y,z,w)
    ip_tuple = socket.ip_to_tuple(myip)
    # generate a broadcast address to port 9999
    # (it's ok and easier to generate it as a 5 number tuple)
    broadcast = (ip_tuple[0],ip_tuple[1],ip_tuple[2],255,9999)
    print(myip,ip_tuple,broadcast)
    # create an UDP socket and bind it to port 9999
    sock = socket.socket(type=socket.SOCK_DGRAM)
    sock.bind(9999)
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

        
# this function will be used as a thread
# sending every 2 seconds a message to all
# the udp sockets listening on port 9999 
def ping():
    while True:
        print("Sending")
        sock.sendto("Hello Zerynth!",broadcast)
        sleep(2000)
        
# launch it!
thread(ping)

# in the main thread we listen for incoming udp packets
while True:
    print("Receiving pings")
    try:
        # recvfrom returns both the packet data and the address of the sender
        data,address = sock.recvfrom(32)
        # since we bind to 9999 we also receive the packets we sent
        # check for it by comparing just the ip address (without the port)
        if address[0]!=myip:
            print("Received ping from",address,"=>",str(data))
        else:
            print("Received ping from myself!")
    except Exception as e:
        print(e)
# uplink this script to more than one board and check

Wifi Scan

ZERYNTH wifi scan
==================

This example explains how to scan for wifi networks.
################################################################################
# Zerynth wifi scan
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# import streams & socket
import streams
import socket

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# FOR THIS EXAMPLE TO WORK, A NETWORK DRIVER MUST BE SELECTED BELOW

# uncomment the following line to use the CC3000 driver (Particle Core or CC3000 Wifi shields)
# from texas.cc3000 import cc3000 as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# a list of security strings
wifi_sec=["Open","WEP","WPA","WPA2"]
try:
    print("Scanning for 15 seconds...")
    # start scanning for 15000 milliseconds
    res = wifi.scan(15000)
    
    # if everything goes well, res is a sequence of tuples
    # each tuple contains:
    # -ssid: the name of the network
    # -sec: the security type of the network, from 0 to 3
    # -rssi: the strength of the signal, from 0 to 127
    # -bssid: the mac address of the access point
    for ssid,sec,rssi,bssid in res:
        print(ssid,"::",wifi_sec[sec],":: strength ",rssi*100/127)
except Exception as e:
    print(e)

HTTP Time

ZERYNTH Time API
=================

This example connects via HTTP to timeapi.org to get the current UTC time 


################################################################################
# Zerynth Time API
#
# Created: 2015-08-17 16:44:58.640097
#
################################################################################

# import streams
import streams
import json

# import the wifi interface
from wireless import wifi

# import the http module
import requests

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# THIS EXAMPLE IS SET TO WORK WITH BCM43362 WIFI DRIVER

# uncomment the following line to use the espressif esp8266 wifi driver (NodeMcu v2, Adafruit Feather Huzzah, Wemos d1 Mini, ...)
# from espressif.esp8266wifi import esp8266wifi as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
from broadcom.bcm43362 import bcm43362 as wifi_driver

# uncomment the following line to use the ESP32 driver (Sparkfun Esp32 Thing, Olimex Esp32, ...)
# from espressif.esp32net import esp32wifi as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# let's try to connect to timeapi.org to get the current UTC time
for i in range(3):
    try:
        print("Trying to connect...")
        # we need to impersonate a web browser: as easy as setting the http user-agent header
        user_agent = {"user-agent":"Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405"}
        # go get that time!
        # url resolution and http protocol handling are hidden inside the requests module
        response = requests.get("http://www.worldtimeserver.com/handlers/GetData.ashx",{"action":"GCTData"},headers=user_agent)
        # let's check the http response status: if different than 200, something went wrong
        print("Http Status:",response.status)
        # if we get here, there has been no exception, exit the loop
        break
    except Exception as e:
        print(e)


try:
    # check status and print the result
    if response.status==200:
        print("Success!!")
        print("-------------")
        print("And the result is:",response.content)
        print("-------------")
        js = json.loads(response.content)
        print("City:",js["City"])
        print("Date:",js["FormattedDate"])
        print("Time:",js["ThisTime"])
except Exception as e:
    print("ooops, something very wrong! :(",e)
    

HTTP Weather

ZERYNTH Weather
=================

This example connects to openweathermap.org, queries for weather conditions and prints the result.
################################################################################
# Zerynth Weather
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################



# import streams & socket
import streams
import socket

# import json parser, will be needed later
import json

# import the wifi interface
from wireless import wifi

# import the http module
import requests

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# THIS EXAMPLE IS SET TO WORK WITH ESP8266 WIFI DRIVER

# uncomment the following line to use the espressif esp8266 wifi driver (NodeMcu v2, Adafruit Feather Huzzah, Wemos d1 Mini, ...)
from espressif.esp8266wifi import esp8266wifi as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

# uncomment the following line to use the ESP32 driver (Sparkfun Esp32 Thing, Olimex Esp32, ...)
# from espressif.esp32net import esp32wifi as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()


# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# let's try to connect to openweathermap.org to get some weather info
# for this example to work you need a openweathermap API key
# if you don't have one, you can get one for free here: http://openweathermap.org/price

# type here your API key!
# or you can use ours...however, if our calls quota is exceded 
# the example won't work :(
api_key = "bd4ba90e2b397e24a925e436a9d8fed9"
        
for i in range(3):
    try:
        print("Trying to connect...")
        # to get weather info you need to specify a correct api url
        # there are a lot of different urls with different functions
        # they are all documented here http://openweathermap.org/api
        
        # let's put the http query parameters in a dict
        params = {
            "APPID":api_key,
            "q":"Pisa"   # <----- here it goes your city
        }
        
        # the following url gets weather information in json based on the name of the city
        url="http://api.openweathermap.org/data/2.5/weather"
        # url resolution and http protocol handling are hidden inside the requests module
        response = requests.get(url,params=params)
        # if we get here, there has been no exception, exit the loop
        break
    except Exception as e:
        print(e)


try:
    # check status and print the result
    if response.status==200:
        print("Success!!")
        print("-------------")
        # it's time to parse the json response
        js = json.loads(response.content)
        # super easy!
        print("Weather:",js["weather"][0]["description"],js["main"]["temp"]-273,"degrees")
        print("-------------")
except Exception as e:
    print("ooops, something very wrong! :(",e)



HTTP Methods

HTTP Methods
============

This example connects via HTTP to httpbin.org and tests each Zerynth supported HTTP method


################################################################################
# Zerynth HTTP Methods
#
# Created: 2017-09-19 12:35:25.155721
# Authors: M. Cipriani
################################################################################

# import streams
import streams
import json

# import the wifi interface
from wireless import wifi

# import the http module
import requests

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# THIS EXAMPLE IS SET TO WORK WITH ESP32 WIFI DRIVER

# uncomment the following line to use the espressif esp8266 wifi driver (NodeMcu v2, Adafruit Feather Huzzah, Wemos d1 Mini, ...)
# from espressif.esp8266wifi import esp8266wifi as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

# uncomment the following line to use the ESP32 driver (Sparkfun Esp32 Thing, Olimex Esp32, ...)
from espressif.esp32net import esp32wifi as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Zerynth",wifi.WIFI_WPA2,"zerynthwifi")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

url = "http://httpbin.org/"

tests = [
    {
        "title": "Testing GET Method...",
        "method": requests.get,
        "url": url+"get",
        "params": {"test": "query_string"}
    },
    {
        "title": "Testing POST Method...",
        "method": requests.post,
        "url": url+"post",
        "json": {"test": "json_data"}
    },
    {
        "title": "Testing PUT Method...",
        "method": requests.put,
        "url": url+"put",
        "data": {"test": "urlencoded_data"}
    },
    {
        "title": "Testing PATCH Method...",
        "method": requests.patch,
        "url": url+"patch",
        "data": {"test": "urlencoded_data"}
    },
    {
        "title": "Testing DELETE Method...",
        "method": requests.delete,
        "url": url+"delete",
    },
    {
        "title": "Testing HEAD Method...",
        "method": requests.head,
        "url": url+"get",
    },
    {
        "title": "Testing OPTIONS Method...",
        "method": requests.options,
        "url": url+"get",
    }
]

print("---------------------------------")
for test in tests:
    try:
        print(test["title"])
        if "params" in test:
            response = test["method"](test["url"], params=test["params"])
        elif "json" in test:
            response = test["method"](test["url"], json=test["json"])
        elif "data" in test:
            response = test["method"](test["url"], data=test["data"])
        else:
            response = test["method"](test["url"])
        print("Http Status:",response.status)
        print("Http Headers:",response.headers)
        print("Http Content:",response.content)
        print("---------------------------------")
        response = None
    except Exception as e:
        print(e)
    sleep(2000)

Secure HTTP

Secure HTTP
===========

This example connects to https://howsmyssl.com/a/check and displays info about the SSL/TLS connection
################################################################################
# Zerynth Secure Sockets
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import json
# import the wifi interface
from wireless import wifi
# import the http module
import requests

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# This example can be used as is with ESP32 based devices
from espressif.esp32net import esp32wifi as wifi_driver


streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()


# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# let's try to connect to https://www.howsmyssl.com/a/check to get some info
# on the SSL/TLS connection

# retrieve the CA certificate used to sign the howsmyssl.com certificate
cacert = __lookup(SSL_CACERT_DST_ROOT_CA_X3)

# create a SSL context to require server certificate verification
ctx = ssl.create_ssl_context(cacert=cacert,options=ssl.CERT_REQUIRED|ssl.SERVER_AUTH)
# NOTE: if the underlying SSL driver does not support certificate validation
#       uncomment the following line!
# ctx = None


for i in range(3):
    try:
        print("Trying to connect...")
        url="https://www.howsmyssl.com/a/check"
        # url resolution and http protocol handling are hidden inside the requests module
        user_agent = {"User-Agent": "curl/7.53.1", "Accept": "*/*" }
        # pass the ssl context together with the request
        response = requests.get(url,headers=user_agent,ctx=ctx)
        # if we get here, there has been no exception, exit the loop
        break
    except Exception as e:
        print(e)


try:
    # check status and print the result
    if response.status==200:
        print("Success!!")
        print("-------------")
        # it's time to parse the json response
        js = json.loads(response.content)
        # super easy!
        for k,v in js.items():
            if k=="given_cipher_suites":
                print("Supported Ciphers")
                for cipher in v:
                    print(cipher)
                print("-----")
            else:
                print(k,"::",v)
        print("-------------")
except Exception as e:
    print("ooops, something very wrong! :(",e)

Resources

ZERYNTH Resources
====================

This example explains the use of flash resources.

################################################################################
# Zerynth Resources
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

streams.serial()

# new_resource is a builtin that includes the file specified
# in the generated bytecode
# remember: the file used as a resource must be added to the project!
new_resource("mytxt.txt")

# to open resources saved by new_resource
# a specific url must be passed to open
# once opened, methods like read, readline and seek can be used!
ff = open("resource://mytxt.txt")

print("Opening resource...")
while True:
    
    # let's read line by line and print
    line = ff.readline()
    
    # if line is empty, we are at the end of file
    if not line:
        break
        
    print("Line:",line)

# easy!
print("Done!")
    

Flash Internal

Flash Internal
==============

Writing and reading internal flash files.
################################################################################
# iflash
#
# Created: 2016-03-22 15:54:21.232663
#
################################################################################

import streams
import json
import flash

## Warning! This example works on the Particle Photon only!
# You need to change the flash address to use another board
#  --> For Sam3X based boards you can safely use 0xe0000

streams.serial()


print("create flash file")

# open a 512 bytes FlashFileStream at address 0x80E0000
ff = flash.FlashFileStream(0x80E0000,512)

print("reading flash file")

for i in range(30):
    print(i,"->",str(ff[i]))

print("writing flash file")

sleep(1000)

hh = {
    "type":"thing",
    "data":23.5
}

ds = json.dumps(hh)

# save length and json to flash
ff.write(len(ds))
ff.write(ds)

ff.flush()

ff.seek(0,streams.SEEK_SET)

print("reading flash file")

n = ff.read_int()

for i in range(n+4):
    print(i,"->",str(ff[i]))

SpiFlash

Spi Flash
=========

An example of how to use the spiflash library to read Spi Flash chips.
################################################################################
# SpiFlash Example
#
# Created: 2016-04-21 19:16:44.440555
#
################################################################################

import spiflash
import streams

streams.serial()


my_flash = spiflash.SpiFlash(SPI0, D25)

my_flash.erase_sector(0x30122)

to_w = [235,166,128,124,65,66]
# write data through bracket notation
my_flash[0x30122] = to_w

print("---")

# read 8 bytes starting from 0x30122 address
for x in my_flash.read_data(0x30122,8):
    print(x)

print("---")

# read the same 8 bytes through bracket notation
for x in my_flash[0x30123:0x30123+8]:
    print(x)

print("---")

SpiSD

Spi SD
======

An example of how to use spisd libray to read SD cards block by block.
################################################################################
# SpiSD Example
#
# Created: 2016-04-29 12:37:53.316436
#
################################################################################

import spisd
import streams

streams.serial()


my_sd = spisd.SpiSD(SPI0, D25)
data = bytearray(512*2)
for i in range(512*2):
    data[i] = 166

# write 512 bytes of data starting from 3rd block
my_sd.write_data(3,data)

# read 512*3 bytes of data starting from 3rd block
for i, x in enumerate(my_sd.read_data(3,3)):
    print(hex(0x200*3+i),": ",x)

Filesystem

Filesystem
==========

A simple example to show the filesystem support in Zerynth (FATFS on SD with SPI)
import streams

import fatfs # import driver module
import os    # import file/directory management module

streams.serial()


# mount my SD card as volume 0 through SPI protocol
fatfs.mount('0:', {"drv": SPI0, "cs": D25, "clock": 1000000} )

# create "zerynth.txt" file and open it for read/write operations
ww = os.open('0:zerynth.txt', 'w+')

# write a string on it, flushing data immediately (not waiting for file to be closed)
ww.write("Zerynth allows me to easily manage files, cool.", sync = True)


# ops, I forgot what I wrote...
# not a real problem problem using Zerynth

# back to the start
ww.seek(0)
print("I wrote: ", ww.read())

ww.close()

# files and directories in root folder?
print(os.listdir('.'))


# a folder for zerynth stuff is needed
if not os.exists("0:zerynth_stuff"):
    os.mkdir("0:zerynth_stuff")
    
# copy my cool file    
os.copyfile("zerynth.txt","zerynth_stuff/zerynth_cool.txt")
os.chdir("0:zerynth_stuff")

# check if anything went wrong
print("in ", os.getcwd())
print(os.listdir('.'))

print("SUCCESS!")

MCU Reset

=========
MCU Reset
=========

A simple example showing how to soft reset the microcontroller from Python.
###############################################################################
# MCU Reset
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################


# import the mcu module
import mcu
import streams

# open the default serial port, the output will be visible in the serial console
streams.serial()  

resetting = False
# define a simple function to be called on interrupt
def reset():
    global resetting
    resetting=True

# on button pressed, call reset
# >>>> if the board hasn't a button, change BTN0 to a digital pin
#      and use a jumper wire to simulate a falling edge <<<<
onPinFall(BTN0,reset)

# loop forever
while True:
    print("Hello Zerynth!")
    sleep(1000)
    # check for the need to reset
    if resetting:
        print("Resetting in 3 seconds!!")
        sleep(3000)
        mcu.reset()
        # bye!

C Language Interface

C Interface
===========

This advanced example shows how to call C functions from Python.

################################################################################
# C Interface
#
# Created: 2016-01-17 10:06:10.333915
#
################################################################################

import streams

streams.serial()

# define a Python function decorated with c_native.
# This function has no body and will instead call
# the C function specified in the decorator.
# The source file(s) where to find the C function must be given (cdiv.c)
@c_native("_my_c_function",["cdiv.c"],[])
def c_division(a,b):
    pass


while True:
    a = random(0,100)
    b = random(0,10)
    try:
        # call the c_division function with random values
        c = c_division(a,b)
        print(a,"/",b,"=",c)
    except Exception as e:
        print(e)
    sleep(1000)

Crypto Hash

Secure Hash Functions
=====================

A simple example to introduce Secure Hashes of the crypto module
################################################################################
# Secure Hash
#
# Created by Zerynth Team 2017 CC
# Authors: G.Baldi
################################################################################

import streams

# import all supported hash functions
from crypto.hash import md5 as md5
from crypto.hash import sha1 as sha1
from crypto.hash import sha2 as sha2
from crypto.hash import sha3 as sha3
from crypto.hash import keccak as keccak
# also import HMAC
from crypto.hash import hmac as hmac

# open stdout
streams.serial()

message = "Zerynth"

while True:
    try:
        ss = md5.MD5()
        ss.update(message)
        print("MD5: ",ss.hexdigest())

        ss = sha1.SHA1()
        ss.update(message)
        print("SHA1:",ss.hexdigest())
        
        ss = sha2.SHA2(sha2.SHA512)
        ss.update(message)
        print("SHA2:",ss.hexdigest())
        
        ss = sha3.SHA3()
        ss.update(message)
        print("SHA3:",ss.hexdigest())

        ss = keccak.Keccak()
        ss.update(message)
        print("KECCAK:",ss.hexdigest())

        # generate a hmac with key="Python" and sha1 hash
        hh = hmac.HMAC("Python",sha1.SHA1())
        hh.update(message)
        print("HMAC:",hh.hexdigest())
    except Exception as e:
        print(e)
    sleep(2000)

Crypto ECC

Elliptic Curve Cryptography
===========================

A simple example to introduce ECDSA primitives.
################################################################################
# Elliptic Curve Cryptography
#
# Created by Zerynth Team 2017 CC
# Authors: G. Baldi
################################################################################

import streams

# import ecc and sha1 modules
from crypto.ecc import ecc as ec
from crypto.hash import sha1 as sha1

streams.serial()

message = "Zerynth"

# import a Public Key for SECP256R1
pb = ec.hex_to_bin("7A181C7D3AD54EC3817CBAF86EA4E003AD492D8569102392A6EFE0C27E471A65553918EA1BAC86A68C78A30E9FE725EA499E14BEA96C3FE85E2267B74385E56B")
# import a Private Key for SECP256R1
pv = ec.hex_to_bin("6D5BE10E67D479FF99421A8DE030E2B4C5323EE477DA4C17420936CAC49C261E")

while True:
    # calculate hash of message
    ss = sha1.SHA1()
    ss.update(message)
    digest = ss.digest()

    # Calculate non deterministic signature of digest
    # for SECP256R1 and pv
    signature = ec.sign(ec.SECP256R1,digest,pv)
    
    # Calculate the deterministic signature of digest using SHA1
    deterministic_signature = ec.sign(ec.SECP256R1,digest,pv,deterministic=sha1.SHA1())

    print("PVKEY:",ec.bin_to_hex(pv))
    print("PBKEY:",ec.bin_to_hex(pb))
    # this changes each loop because of random number generator
    print("SIGNED:",ec.bin_to_hex(signature))
    # this is always the same
    print("SIGNED (det)",ec.bin_to_hex(deterministic_signature))

    print("VERIFY SIGNATURE:", ec.verify(ec.SECP256R1,digest,signature,pb))
    print("VERIFY SIGNATURE (det):", ec.verify(ec.SECP256R1,digest,deterministic_signature,pb))
    # tampered digests are detected
    print("VERIFY TAMPERED:", ec.verify(ec.SECP256R1,digest+b'\x00',signature,pb))
    print("-"*20)
    sleep(2000)

Powersaving

Powersaving
===========

This example shows the most important features of Powersaving enabled VMs:

* The ability to choose which low power mode to enter and how to exit
* The ability to save status on a special purpose memory guaranteed to be preserved after exiting the low power mode
################################################################################
# Powersaving
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

##
## This example only works on a Powersaving enabled Virtual Machine!
##

import streams
# import the Power Management module
# Check documentation here: https://docs.zerynth.com/latest/official/core.zerynth.stdlib/docs/official_core.zerynth.stdlib_pwr.html
import pwr

streams.serial()

# wake up reasons dictionary
reasons = {
    pwr.PWR_RESET:"System Reset",
    pwr.PWR_INTERRUPT: "Event on WAKEUP pin",
    pwr.PWR_TIMEOUT: "Timeout"
}

# modes and descriptions
modes = [
    (pwr.PWR_SLEEP, "Sleep mode"),
    (pwr.PWR_STOP, "Stop mode"),
    (pwr.PWR_STANDBY, "Standby mode")
]

# some status variables
slept = 0
wokeup = 0
sleep_counter = 0

# callback for Wake Up events on pins
def wakeup():
    print("Hello!")

# function to prepare for and enter low power mode
def sleepfn(delay,mode):
    global slept,wokeup
    print("Going to sleep for",delay,"milliseconds in",modes[mode][1])
    sleep(100)
    # call go_to_sleep and get the amount of time spent sleeping
    # !! the VM is suspended here !!
    slept = pwr.go_to_sleep(delay,modes[mode][0])
    # if we reach this point, something caused a Wake Up from a low power mode
    # if we don't reach here, the device exited from a standby mode with a system reset

    # retrieve the Wake Up reason
    wokeup = pwr.wakeup_reason()
    print("SLEPT FOR",slept)
    print("My wake up reason:",reasons.get(wokeup,"Unknown"))


try:

    # retrieve the Wake Up reason
    wokeup = pwr.wakeup_reason()
    
    # retrieve sleep_counter from special purpose memory if supported
    try:
        sleep_counter = pwr.get_status_byte(0)
        print("Special purpose memory supported!")
    except Exception as e:
        print("Special purpose memory not supported :(")
    
    # print status at VM startup
    print("Wake up reason at startup:",reasons.get(wokeup,"Unknown"))
    print("Tried to sleep",sleep_counter,"times")

    
    # configure button to do something
    # depending on the platform this is enough to configure a Wake Up event
    # on some platforms only specific pins have the Wake Up property
    # (If the device has no button, configure another pin! [Try D6 on MKR1000 and D8 on Hexiwear])
    pinMode(BTN0,INPUT_PULLUP)
    onPinFall(BTN0, wakeup, debounce=1000)
    
    cnt = 5
    mode = 0
    print("Countdown!")
    while True:
        # print the countdown
        print(cnt)
        sleep(1000)
        
        cnt-=1
        if cnt==0:
            cnt=5
            try:
                # save number of sleeps in special purpose memory
                sleep_counter=(sleep_counter+1)%256
                try:
                    pwr.set_status_byte(0,sleep_counter)
                except:
                    # ignore if special purpose memory not supported
                    pass
                # enter a low power mode for 5 seconds or less
                # (press the button while sleeping to check if Wake Up is available in this mode)
                sleepfn(5000,mode)
            except Exception as e:
                print(modes[mode][1],"not supported!")
                print(e)
            mode=(mode+1)%len(modes)
            print("Countdown!")
except Exception as e:
    print(e)
    
    
# Expected results by architecture and mode for Wake Up on pin event
#
#      MODE  |      SLEEP        STOP                 STANDBY
# MCU        |
# -------------------------------------------------------------------
#            |
# STM32F     |       OK           OK                Only on pin PA0
#            |
# -------------------------------------------------------------------
#            |
# SAMD21     |       OK           No               Mode not supported
#            |
# --------------------------------------------------------------------
#            |
# NXP K64    |       OK           OK               Only on WakeUp pins 
#            |
# --------------------------------------------------------------------
#            |
# ESP8266    |    Unsupported   Unsupported    Only works for Gpio 16
#            |
# --------------------------------------------------------------------


Watchdogs

Watchdogs
=========

A basic example showing the watchdog functionalities in a Secure Fimrware enabled VM.
################################################################################
# Watchdogs
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

##
## This example only works on a Secure Firmware enabled Virtual Machine!
##

import streams
# import the Secure Firmware module
# Check documentation here: https://docs.zerynth.com/latest/official/core.zerynth.stdlib/docs/official_core.zerynth.stdlib_sfw.html
import sfw

streams.serial()

sleep(2000)

# Check for reset reason
try:
    print("Watchdog triggered:",sfw.watchdog_triggered())
except Exception as e:
    print("Watchdog not suppported by this Virtual Machine!")
    while True:
        sleep(1000)

# Do something without fearing a reset
for x in range(10):
    sleep(1000)
    print("Printing something for a while, no watchdog can reset me! 8‑D")



# Configure watchdog in normal mode with a 5 seconds timeout
print("Configuring watchdog to a 5 seconds timeout...")
sfw.watchdog(0,5000)
sleep(100)

# Kick the watchdog every second
for x in range(10):
    sleep(1000)
    sfw.kick()
    print("Kick!")
    
# Stop kicking and wait for reset
while True:
    print("Printing something for a while waiting for the watchdog! D-8")
    sleep(1000)