2 This file is part of the Firmware project to interface with small Async or Neuromorphic chips
3 Copyright (C) 2022-2023 Ole Richter - University of Groningen
4 Copyright (C) 2022 Benjamin Hucko
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>.
20// -DARDUINO_SAMD_MKRZERO -DARDUINO_ARCH_SAMD -DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ -DF_CPU=48000000L
21// -D__IMXRT1062__ -DARDUINO_TEENSY41 -DF_CPU=600000000 -DTEENSYDUINO
26#include "core_ring_buffer.h"
27#include "core_intervaltimer_samd21.h"
28#include "core_instruction_exec.h"
34 This programm is supposed to be used for interfacing with small Async or Neuromorphic chips,
35 the pin and interface configuration is uploaded on runtime via configuration packets,
36 so for most chips/modules a change of the uC firmware is not nessesary.
38 the Idea behind the firmware is that you can send command packets with a exec time in the future,
39and the command is executed at that time via interrupt. (see instruction_exec.h/cpp)
40 if you send exec_time=0 the execution is done right away. The exec_time needs to be sorted and assending.
41 the execuion is done via interrupts the execution only happens every ~100us => see instruction_exec.h
42 timesteps are in usec and the role over occurs after ~71min after boot of the uC. roleover is not supported.
44 the folloeing interfaces are supported:
45 - SPI - Serial Periferal Interface for memory and fifo access (see "Interface_spi.h/cpp")
46 - AER - paralell databus with 4-phase handshake (see "AER_tochip.h/cpp" and "AER_from_chip.h/cpp")
47 - PIN - manual pin raising and lowering (see "Interface_pin.h/cpp")
50 see datatypes.h for all available commands and thier use.
52 to start recording and execution set the TIME to anything other than 0, to stop execution and recording sent TIME to 0.
54 recording of events is handeled in "isr_helper.h/cpp"
56 the coding style is following the Arduino Style of having interfaces staticly allocatated for access.
57 In a future version this shoud be at least changed to static Object Oriented Programing
63 setup starts the serial connection and allocates the ring buffers
64 aswell as sets the interruptpriority for command execution
68 Serial.begin(115200); // the speed is ignored the USB native speed is used.
71 myTimer.priority(200);
76 the main loop just handels comunication with the host via the serial interface and instuction execution if exec_time == 0,
77 in all other cases the instruction is stored in the instruction ring buffer.
80 if (Serial.available() >= sizeof(packet_t)) {
82 // read instruction packet
83 packet_t current_instruction;
85 // because we use different storage allignment we need to transfer each byte individual
86 // also checks if the communication protocol needs to be aligned
88 for (position = 0; position < sizeof(packet_t); position++){
89 Serial.readBytes(&(current_instruction.bytes[position]), 1);
90 // check if the PC reqests a communication protocol alignment by writing 9 bytes
91 // of IN_ALIGN_COMMUNICATION_PROTOCOL (255) so that uC catches one of them as a header
92 if (position == 0 && current_instruction.bytes[0] == IN_ALIGN_COMMUNICATION_PROTOCOL){
94 Serial.readBytes(&(current_instruction.bytes[0]), 1);
95 } while (current_instruction.bytes[0] == IN_ALIGN_COMMUNICATION_PROTOCOL);
97 for (position_out = 0; position_out < sizeof(packet_t); position_out++) Serial.write(IN_ALIGN_COMMUNICATION_PROTOCOL);
101 // exec instruction if exec_time == 0
102 // else if instruction buffer is not full store instruction
103 if (current_instruction.data.exec_time == 0) {
104 exec_instruction(¤t_instruction, false);
107 add_input_packet(¤t_instruction);
111 // write one element of the output buffer
112 if (output_buffer_read && Serial.availableForWrite()){
113 send_output_ring_buffer_first();
116 // send error if output buffer is full, DoS
117 //else if (output_ring_buffer_start == (output_ring_buffer_next_free + 1) % OUTPUT_BUFFER_SIZE) {
118 // error_message_bypass_buffer(OUT_ERROR,OUT_ERROR_OUTPUT_FULL,output_ring_buffer_next_free);
121 if (loop_runs_without_gpio_interrups > 0){
122 loop_runs_without_gpio_interrups--;
123 if (loop_runs_without_gpio_interrups == 0){
124 enable_gpio_interrupt();