├── configure.sh ├── Nanpy ├── consts.h ├── cfg_all.h ├── BaseClass.cpp ├── freeram.h ├── intdefs.h ├── UltrasonicWrapper.h ├── ColorSensorWrapper.h ├── FreqCount.h ├── CounterClass.h ├── InfoClass.h ├── RegisterClass.h ├── DefineClass.h ├── ArduinoCoreClass.h ├── ToneWrapper.h ├── RAMClass.h ├── EspClass.h ├── EEPROMClass.h ├── WatchdogClass.h ├── ArduinoClass.h ├── WireClass.h ├── DHTClass.h ├── MCP41xxxClass.h ├── ServoClass.h ├── TLC5947Class.h ├── ToneWrapper.cpp ├── StepperClass.h ├── OneWireClass.h ├── UltrasonicClass.h ├── LiquidCrystalClass.h ├── DallasTemperatureClass.h ├── CapacitiveSensorClass.h ├── ColorSensorClass.h ├── LiquidCrystalClass_I2C.h ├── UltrasonicClass.cpp ├── InfoClass.cpp ├── ColorSensorClass.cpp ├── EEPROMClass.cpp ├── CounterClass.cpp ├── MCP41xxxClass.cpp ├── ComChannel.h ├── ToneClass.cpp ├── TLC5947Class.cpp ├── CapacitiveSensorClass.cpp ├── ColorSensorWrapper.cpp ├── DHTClass.cpp ├── RAMClass.cpp ├── cfg_check.h ├── generated_intdefs.h ├── StepperClass.cpp ├── ArduinoCoreClass.cpp ├── MethodDescriptor.h ├── WatchdogClass.cpp ├── ServoClass.cpp ├── WireClass.cpp ├── ArduinoClass.cpp ├── UltrasonicWrapper.cpp ├── LiquidCrystalClass_I2C.cpp ├── BaseClass.h ├── cfg_defaults.h ├── freeram.c ├── OneWireClass.cpp ├── LiquidCrystalClass.cpp ├── SlimArray.h ├── ToneClass.h ├── RegisterClass.cpp ├── FreqCount.cpp ├── DefineClass.cpp ├── DallasTemperatureClass.cpp ├── MethodDescriptor.cpp ├── EspClass.cpp ├── Nanpy.ino ├── ComChannel.cpp ├── timers.h └── generated_mcu.h ├── codegen ├── intdefs.txt ├── intdefs.py ├── README.md └── __init__.py ├── .gitignore ├── .travis.yml ├── CONTRIBUTORS ├── README.md ├── LICENSE ├── tests └── test_build.py └── sample_cfg.h /configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cp sample_cfg.h Nanpy/cfg.h 4 | -------------------------------------------------------------------------------- /Nanpy/consts.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MAX_READ_BUFFER_SIZE 50 4 | 5 | -------------------------------------------------------------------------------- /Nanpy/cfg_all.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cfg.h" 4 | #include "cfg_defaults.h" 5 | #include "cfg_check.h" 6 | -------------------------------------------------------------------------------- /Nanpy/BaseClass.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "BaseClass.h" 3 | 4 | using namespace nanpy; 5 | 6 | SlimArray Register::classes; 7 | -------------------------------------------------------------------------------- /Nanpy/freeram.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" 5 | { 6 | #endif 7 | 8 | int free_ram1(); 9 | int free_ram2(); 10 | int free_ram3(); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /Nanpy/intdefs.h: -------------------------------------------------------------------------------- 1 | 2 | // const int variables cannot be checked automatically like defines 3 | 4 | DEFINE(A0) 5 | 6 | #ifdef ARDUINO_ARCH_AVR 7 | DEFINE(SS) 8 | DEFINE(MOSI) 9 | DEFINE(MISO) 10 | DEFINE(SCK) 11 | #endif 12 | 13 | 14 | -------------------------------------------------------------------------------- /codegen/intdefs.txt: -------------------------------------------------------------------------------- 1 | NUM_DIGITAL_PINS 2 | RAMSTART 3 | RAMEND 4 | XRAMEND 5 | E2END 6 | FLASHEND 7 | SPM_PAGESIZE 8 | E2PAGESIZE 9 | F_CPU 10 | ARDUINO 11 | __AVR_LIBC_DATE_ 12 | __AVR_LIBC_VERSION__ 13 | IRAM0_ADDR 14 | IRAM0_SIZE 15 | IRAM1_ADDR 16 | IRAM1_SIZE 17 | -------------------------------------------------------------------------------- /Nanpy/UltrasonicWrapper.h: -------------------------------------------------------------------------------- 1 | namespace nanpy { 2 | 3 | class UltrasonicWrapper { 4 | 5 | private: 6 | int echo, trig, conversionFactor; 7 | 8 | public: 9 | UltrasonicWrapper(int echoPin, int trigPin, bool useInches); 10 | float getDistance(); 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /Nanpy/ColorSensorWrapper.h: -------------------------------------------------------------------------------- 1 | namespace nanpy { 2 | 3 | class ColorSensorWrapper { 4 | 5 | private: 6 | int s0, s1, s2, s3, sensorOut; 7 | 8 | public: 9 | ColorSensorWrapper(int s0, int s1, int s2, int s3, int sensorOut); 10 | int getColor(char color); 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /Nanpy/FreqCount.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class FreqCountClass { 6 | public: 7 | static void begin(uint16_t msec); 8 | static uint8_t available(void); 9 | static uint32_t read(void); 10 | static void end(void); 11 | }; 12 | 13 | extern FreqCountClass FreqCount; 14 | 15 | -------------------------------------------------------------------------------- /Nanpy/CounterClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseClass.h" 4 | #include "MethodDescriptor.h" 5 | 6 | namespace nanpy { 7 | class CounterClass : public BaseClass { 8 | 9 | public: 10 | void elaborate( nanpy::MethodDescriptor* m ); 11 | const char* get_firmware_id(); 12 | 13 | }; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /Nanpy/InfoClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseClass.h" 4 | #include "MethodDescriptor.h" 5 | 6 | namespace nanpy { 7 | class InfoClass : public BaseClass { 8 | 9 | public: 10 | void elaborate( nanpy::MethodDescriptor* m ); 11 | const char* get_firmware_id(); 12 | 13 | }; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /Nanpy/RegisterClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "BaseClass.h" 3 | #include "MethodDescriptor.h" 4 | 5 | namespace nanpy { 6 | class RegisterClass : public BaseClass { 7 | 8 | public: 9 | void elaborate( nanpy::MethodDescriptor* m ); 10 | const char* get_firmware_id(); 11 | 12 | }; 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /Nanpy/DefineClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseClass.h" 4 | #include "MethodDescriptor.h" 5 | 6 | namespace nanpy { 7 | class DefineClass : public BaseClass { 8 | 9 | public: 10 | void elaborate( nanpy::MethodDescriptor* m ); 11 | const char* get_firmware_id(); 12 | 13 | }; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /Nanpy/ArduinoCoreClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseClass.h" 4 | #include "MethodDescriptor.h" 5 | 6 | namespace nanpy { 7 | class ArduinoCoreClass : public BaseClass { 8 | 9 | public: 10 | void elaborate( nanpy::MethodDescriptor* m ); 11 | const char* get_firmware_id(); 12 | 13 | }; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /Nanpy/ToneWrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef TONE_WRAPPER_H 2 | #define TONE_WRAPPER_H 3 | 4 | namespace nanpy { 5 | class ToneWrapper { 6 | 7 | private: 8 | 9 | int pin; 10 | 11 | public: 12 | 13 | ToneWrapper(int pin) : pin(pin) {} 14 | void play(int note, int duration); 15 | void stop(void); 16 | 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /Nanpy/RAMClass.h: -------------------------------------------------------------------------------- 1 | #ifndef RAM_CLASS 2 | #define RAM_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | namespace nanpy { 8 | class RAMClass : public BaseClass { 9 | 10 | public: 11 | void elaborate( nanpy::MethodDescriptor* m ); 12 | const char* get_firmware_id(); 13 | 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /Nanpy/EspClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //#ifdef ESP8266 4 | 5 | #include "BaseClass.h" 6 | #include "MethodDescriptor.h" 7 | 8 | namespace nanpy { 9 | class EspClass : public BaseClass { 10 | 11 | public: 12 | void elaborate( nanpy::MethodDescriptor* m ); 13 | const char* get_firmware_id(); 14 | 15 | }; 16 | }; 17 | 18 | //#endif 19 | -------------------------------------------------------------------------------- /Nanpy/EEPROMClass.h: -------------------------------------------------------------------------------- 1 | #ifndef EEPROM_CLASS 2 | #define EEPROM_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | namespace nanpy { 8 | class EEPROMClass : public BaseClass { 9 | 10 | public: 11 | void elaborate( nanpy::MethodDescriptor* m ); 12 | const char* get_firmware_id(); 13 | 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /Nanpy/WatchdogClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseClass.h" 4 | #include "MethodDescriptor.h" 5 | 6 | namespace nanpy { 7 | class WatchdogClass : public BaseClass { 8 | 9 | public: 10 | void elaborate( nanpy::MethodDescriptor* m ); 11 | const char* get_firmware_id(); 12 | 13 | }; 14 | }; 15 | 16 | void disable_watchdog_at_startup(); 17 | -------------------------------------------------------------------------------- /Nanpy/ArduinoClass.h: -------------------------------------------------------------------------------- 1 | #ifndef ARDUINO_CLASS 2 | #define ARDUINO_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | namespace nanpy { 8 | class ArduinoClass : public BaseClass { 9 | 10 | public: 11 | void elaborate( nanpy::MethodDescriptor* m ); 12 | const char* get_firmware_id(); 13 | 14 | }; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /Nanpy/WireClass.h: -------------------------------------------------------------------------------- 1 | #ifndef Wire_CLASS 2 | #define Wire_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class Wire; 8 | 9 | namespace nanpy { 10 | class WireClass: public BaseClass { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/DHTClass.h: -------------------------------------------------------------------------------- 1 | #ifndef DHT_CLASS 2 | #define DHT_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class DHT; 8 | 9 | namespace nanpy { 10 | class DHTClass: public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/MCP41xxxClass.h: -------------------------------------------------------------------------------- 1 | #ifndef MCP41XXX_CLASS 2 | #define MCP41XXX_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class MCP41xxx; 8 | 9 | namespace nanpy{ 10 | class MCP41xxxClass: public ObjectsManager{ 11 | public: 12 | void elaborate( nanpy::MethodDescriptor* m); 13 | const char* get_firmware_id(); 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #General 2 | .DS_Store 3 | *~ 4 | *.swp 5 | build/ 6 | 7 | #Arduino 8 | *.o 9 | *.hex 10 | */.dep 11 | */.lib 12 | 13 | #Configuration 14 | Nanpy/cfg.h 15 | makefile/ 16 | 17 | #Internal dev 18 | Nanpy/arduino.mk 19 | Nanpy/Makefile 20 | Nanpy/libraries 21 | 22 | #Python 23 | *.pyc 24 | 25 | # ignore all hidden files... 26 | .* 27 | # ...except: 28 | !.git* 29 | !.travis* 30 | -------------------------------------------------------------------------------- /Nanpy/ServoClass.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVO_CLASS 2 | #define SERVO_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class Servo; 8 | 9 | namespace nanpy { 10 | class ServoClass: public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/TLC5947Class.h: -------------------------------------------------------------------------------- 1 | #ifndef TLC5947_CLASS 2 | #define TLC5947_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class Adafruit_TLC5947; 8 | 9 | namespace nanpy { 10 | class TLC5947Class: public ObjectsManager { 11 | public: 12 | void elaborate( nanpy::MethodDescriptor* m ); 13 | const char* get_firmware_id(); 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /Nanpy/ToneWrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Tone 4 | 5 | #include "ToneWrapper.h" 6 | #include 7 | 8 | void nanpy::ToneWrapper::play(int note, int duration) { 9 | #if defined(__AVR__) 10 | tone(pin, note); 11 | #endif 12 | } 13 | 14 | void nanpy::ToneWrapper::stop(void) { 15 | #if defined(__AVR__) 16 | noTone(pin); 17 | #endif 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /Nanpy/StepperClass.h: -------------------------------------------------------------------------------- 1 | #ifndef STEPPER_CLASS 2 | #define STEPPER_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class Stepper; 8 | 9 | namespace nanpy { 10 | class StepperClass: public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/OneWireClass.h: -------------------------------------------------------------------------------- 1 | #ifndef ONE_WIRE_CLASS 2 | #define ONE_WIRE_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class OneWire; 8 | 9 | namespace nanpy { 10 | class OneWireClass: public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/UltrasonicClass.h: -------------------------------------------------------------------------------- 1 | #ifndef ULTRASONIC_CLASS 2 | #define ULTRASONIC_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | #include "UltrasonicWrapper.h" 7 | 8 | class Ultrasonic; 9 | 10 | namespace nanpy { 11 | class UltrasonicClass: public ObjectsManager { 12 | 13 | public: 14 | void elaborate( nanpy::MethodDescriptor* m ); 15 | const char* get_firmware_id(); 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/LiquidCrystalClass.h: -------------------------------------------------------------------------------- 1 | #ifndef LIQUID_CRYSTAL_CLASS 2 | #define LIQUID_CRYSTAL_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class LiquidCrystal; 8 | 9 | namespace nanpy { 10 | class LiquidCrystalClass : public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /Nanpy/DallasTemperatureClass.h: -------------------------------------------------------------------------------- 1 | #ifndef DALLAS_TEMP_CLASS 2 | #define DALLAS_TEMP_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class DallasTemperature; 8 | 9 | namespace nanpy { 10 | class DallasTemperatureClass: public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/CapacitiveSensorClass.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPACITIVE_SENSOR_CLASS 2 | #define CAPACITIVE_SENSOR_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class CapacitiveSensor; 8 | 9 | namespace nanpy { 10 | class CapacitiveSensorClass : public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/ColorSensorClass.h: -------------------------------------------------------------------------------- 1 | #ifndef COLORSENSOR_CLASS 2 | #define COLORSENSOR_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | #include "ColorSensorWrapper.h" 7 | 8 | class ColorSensor; 9 | 10 | namespace nanpy { 11 | class ColorSensorClass: public ObjectsManager { 12 | 13 | public: 14 | void elaborate( nanpy::MethodDescriptor* m ); 15 | const char* get_firmware_id(); 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Nanpy/LiquidCrystalClass_I2C.h: -------------------------------------------------------------------------------- 1 | #ifndef LIQUID_CRYSTAL_CLASS_I2C 2 | #define LIQUID_CRYSTAL_CLASS_I2C 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | class LiquidCrystal_I2C; 8 | 9 | namespace nanpy { 10 | class LiquidCrystalClass_I2C : public ObjectsManager { 11 | 12 | public: 13 | void elaborate( nanpy::MethodDescriptor* m ); 14 | const char* get_firmware_id(); 15 | 16 | }; 17 | } 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | before_install: 4 | - sudo apt-get update -qq 5 | - sudo apt-get install -y binutils-avr gcc-avr scons python-pip arduino 6 | - wget http://ftp.us.debian.org/debian/pool/main/a/arduino/arduino-core_1.0.5+dfsg2-4_all.deb 7 | - sudo dpkg -i arduino-core_1.0.5+dfsg2-4_all.deb 8 | - sudo rm -f /usr/share/arduino/libraries/Robot_Control/Wire.h 9 | - sudo pip install confduino 10 | - sudo pip install pyavrutils 11 | - sudo pip install path.py 12 | - sudo pip install nose 13 | - sudo pip install nose_ittr 14 | 15 | install: 16 | 17 | script: nosetests -v tests 18 | 19 | -------------------------------------------------------------------------------- /Nanpy/UltrasonicClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #include 4 | #include "UltrasonicClass.h" 5 | #include 6 | 7 | const char* nanpy::UltrasonicClass::get_firmware_id() { 8 | return "Ultrasonic"; 9 | } 10 | 11 | void nanpy::UltrasonicClass::elaborate( MethodDescriptor* m ) { 12 | ObjectsManager::elaborate(m); 13 | 14 | if (strcmp(m->getName(), "new") == 0) { 15 | v.insert(new UltrasonicWrapper(m->getInt(0), m->getInt(1), m->getBool(2))); 16 | m->returns(v.getLastIndex()); 17 | } 18 | 19 | if (strcmp(m->getName(), "get_distance") == 0) { 20 | m->returns(v[m->getObjectId()]->getDistance()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Nanpy/InfoClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Info 4 | 5 | #include "InfoClass.h" 6 | #include 7 | 8 | const char* nanpy::InfoClass::get_firmware_id() 9 | { 10 | return "Info"; 11 | } 12 | 13 | void nanpy::InfoClass::elaborate(nanpy::MethodDescriptor* m) 14 | { 15 | nanpy::SlimArray * classes = Register::get_classes(); 16 | if (strcmp(m->getName(), "count") == 0) 17 | { 18 | m->returns(classes->getSize()); 19 | } 20 | if (strcmp(m->getName(), "name") == 0) 21 | { 22 | int index = m->getInt(0); 23 | m->returns(classes->get(index)->get_firmware_id()); 24 | } 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Written by 2 | ---------- 3 | - Andrea Stagi (https://github.com/astagi) 4 | - Ponty (https://github.com/ponty) 5 | 6 | Contributors 7 | ------------ 8 | - Kevin Ng (kevin.ngkf@gmail.com) 9 | - Andrea Grandi (https://github.com/andreagrandi) 10 | - Tim Marston (tim@ed.am) 11 | - Fernando Molina (Twitter @F_M_A) 12 | - Laurent Désarmes (https://github.com/llaurent) 13 | - Anthony Goodhew (tony.goodhew@ntlworld.com) 14 | - Balz Reber (https://github.com/balzreber) 15 | - Jimmy Henderickx (https://github.com/StryKaizer) 16 | - Balz Reber (https://github.com/balzreber) 17 | - Michal Opler (https://github.com/joppi) 18 | - Stefan Krastanov (https://github.com/Krastanov) 19 | - egarris2 (https://github.com/egarris2) 20 | -------------------------------------------------------------------------------- /Nanpy/ColorSensorClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #include 4 | #include "ColorSensorClass.h" 5 | #include 6 | 7 | const char* nanpy::ColorSensorClass::get_firmware_id() { 8 | return "ColorSensor"; 9 | } 10 | 11 | void nanpy::ColorSensorClass::elaborate( MethodDescriptor* m ) { 12 | ObjectsManager::elaborate(m); 13 | 14 | if (strcmp(m->getName(), "new") == 0) { 15 | v.insert(new ColorSensorWrapper(m->getInt(0), m->getInt(1), m->getInt(2), m->getInt(3), m->getInt(4))); 16 | m->returns(v.getLastIndex()); 17 | } 18 | 19 | if (strcmp(m->getName(), "get_color") == 0) { 20 | char* p = m->getString(0); 21 | m->returns(v[m->getObjectId()]->getColor(*p)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Nanpy/EEPROMClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_EEPROM 4 | 5 | #include 6 | #include "EEPROMClass.h" 7 | #include 8 | 9 | const char* nanpy::EEPROMClass::get_firmware_id() 10 | { 11 | return "EEPROM"; 12 | } 13 | 14 | void nanpy::EEPROMClass::elaborate( nanpy::MethodDescriptor* m ) { 15 | if (strcmp(m->getName(), "write") == 0) { 16 | EEPROM.write(m->getInt(0), m->getInt(1)); 17 | m->returns(0); 18 | } 19 | if (strcmp(m->getName(), "read") == 0) { 20 | m->returns(EEPROM.read(m->getInt(0))); 21 | } 22 | 23 | if (strcmp(m->getName(), "size") == 0) { 24 | m->returns(E2END+1); 25 | } 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nanpy firmware v0.9.6 2 | 3 | [![Travis-CI Status](https://travis-ci.org/nanpy/nanpy-firmware.svg?branch=master)](https://travis-ci.org/nanpy/nanpy-firmware) 4 | 5 | Firmware for Nanpy, a library to use your Arduino board with Python. Read more on Nanpy at https://github.com/nanpy 6 | 7 | ## How to configure 8 | 9 | $ cd firmware 10 | $ ./configure.sh 11 | 12 | You can use Nanpy/cfg.h generated file to configure your Nanpy firmware, selecting the features you want to include and the baud rate. 13 | 14 | ## How to build and install 15 | 16 | Copy Nanpy directory under your "sketchbook" directory, start your Arduino IDE, open Sketchbook/Nanpy, select "Upload". 17 | 18 | ## License 19 | 20 | This software is released under MIT License. Copyright (c) 2012-2015 Andrea Stagi 21 | -------------------------------------------------------------------------------- /Nanpy/CounterClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Counter 4 | 5 | #include "CounterClass.h" 6 | #include "FreqCount.h" 7 | 8 | const char* nanpy::CounterClass::get_firmware_id() 9 | { 10 | return "Counter"; 11 | } 12 | 13 | void nanpy::CounterClass::elaborate(nanpy::MethodDescriptor* m) 14 | { 15 | if (strcmp(m->getName(), "begin") == 0) 16 | { 17 | FreqCount.begin(m->getInt(0)); 18 | m->returns(0); 19 | } 20 | if (strcmp(m->getName(), "available") == 0) 21 | { 22 | m->returns(FreqCount.available()); 23 | } 24 | if (strcmp(m->getName(), "read") == 0) 25 | { 26 | m->returns(FreqCount.read()); 27 | } 28 | if (strcmp(m->getName(), "end") == 0) 29 | { 30 | FreqCount.end(); 31 | m->returns(0); 32 | } 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /Nanpy/MCP41xxxClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg.h" 2 | 3 | #if USE_MCP41xxx 4 | 5 | #include 6 | #include 7 | #include "MCP41xxxClass.h" 8 | #include "SPI.h" 9 | #include 10 | 11 | const char* nanpy::MCP41xxxClass::get_firmware_id(){ 12 | return "MCP41xxx"; 13 | } 14 | 15 | void nanpy::MCP41xxxClass::elaborate( nanpy::MethodDescriptor* m ) { 16 | ObjectsManager::elaborate(m); 17 | 18 | if (strcmp(m->getName(),"new") == 0) { 19 | MCP41xxx* pot; 20 | pot = new MCP41xxx (m->getInt(0)); 21 | pot->begin(); 22 | v.insert(pot); 23 | m->returns(v.getLastIndex()); 24 | } 25 | 26 | if (strcmp(m->getName(), "analogWrite") == 0) { 27 | v[m->getObjectId()]->analogWrite(m->getInt(0), m->getInt(1)); 28 | m->returns(0); 29 | } 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /Nanpy/ComChannel.h: -------------------------------------------------------------------------------- 1 | #ifndef COM_CHANNEL 2 | #define COM_CHANNEL 3 | 4 | #include "cfg_all.h" 5 | #include "consts.h" 6 | 7 | #include 8 | 9 | namespace nanpy { 10 | class ComChannel { 11 | 12 | public: 13 | static char read_buffer[MAX_READ_BUFFER_SIZE]; 14 | static bool available(); 15 | static void connect(); 16 | static void println(String& val); 17 | static void println(const char* val); 18 | static void println(int val); 19 | static void println(unsigned int val); 20 | static void println(float val); 21 | static void println(double val); 22 | static void println(long val); 23 | static void println(unsigned long val); 24 | static void readLine(char* extbuff); 25 | }; 26 | } 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /Nanpy/ToneClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Tone 4 | 5 | #include 6 | #include "ToneClass.h" 7 | #include 8 | 9 | const char* nanpy::ToneClass::get_firmware_id() 10 | { 11 | return "Tone"; 12 | } 13 | 14 | void nanpy::ToneClass::elaborate( nanpy::MethodDescriptor* m ) { 15 | ObjectsManager::elaborate(m); 16 | 17 | if (strcmp(m->getName(),"new") == 0) { 18 | v.insert(new ToneWrapper (m->getInt(0))); 19 | m->returns(v.getLastIndex()); 20 | } 21 | 22 | if (strcmp(m->getName(), "play") == 0) { 23 | v[m->getObjectId()]->play(m->getInt(0), m->getInt(1)); 24 | m->returns(0); 25 | } 26 | 27 | if (strcmp(m->getName(), "stop") == 0) { 28 | v[m->getObjectId()]->stop(); 29 | m->returns(0); 30 | } 31 | }; 32 | #endif 33 | -------------------------------------------------------------------------------- /Nanpy/TLC5947Class.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg.h" 2 | 3 | #if USE_TLC5947 4 | 5 | #include 6 | #include 7 | #include "TLC5947Class.h" 8 | #include 9 | 10 | const char* nanpy::TLC5947Class::get_firmware_id() { 11 | return "TLC5947"; 12 | } 13 | 14 | void nanpy::TLC5947Class::elaborate( MethodDescriptor* m ) { 15 | ObjectsManager::elaborate(m); 16 | 17 | if(strcmp(m->getName(), "new") == 0) { 18 | Adafruit_TLC5947* tlc = new Adafruit_TLC5947(m->getInt(0), m->getInt(1), m->getInt(2), m->getInt(3)); 19 | tlc->begin(); 20 | v.insert(tlc); 21 | m->returns(v.getLastIndex()); 22 | } 23 | 24 | if (strcmp(m->getName(), "setLED") == 0) { 25 | v[m->getObjectId()]->setLED(m->getInt(0), m->getInt(1), m->getInt(2), m->getInt(3)); 26 | m->returns(0); 27 | } 28 | 29 | if (strcmp(m->getName(), "write") == 0) { 30 | v[m->getObjectId()]->write(); 31 | m->returns(0); 32 | } 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /codegen/intdefs.py: -------------------------------------------------------------------------------- 1 | from path import Path 2 | 3 | HEADER = ''' 4 | // Generated file, do not edit! 5 | 6 | #define LONGEST_STRING_IN_INTDEFS_H {0} 7 | 8 | ''' 9 | 10 | TEMPLATE = ''' 11 | #ifdef {0} 12 | DEFINE({0}) 13 | #endif 14 | ''' 15 | 16 | 17 | def main(): 18 | firmware_path = Path(__file__).abspath().parent.parent 19 | # nanpy_path = path(__file__).abspath().parent.parent / 'nanpy' 20 | input_path = Path(__file__).abspath().parent / 'intdefs.txt' 21 | output_path = firmware_path / 'Nanpy' / 'generated_intdefs.h' 22 | 23 | print('reading: %s' % input_path) 24 | print('writing: %s' % output_path) 25 | 26 | lines = [x.strip() for x in input_path.text().splitlines()] 27 | 28 | max_len = max([len(x) for x in lines]) 29 | output = HEADER.format(max_len) 30 | for line in lines: 31 | output += TEMPLATE.format(line) 32 | 33 | output_path.write_text(output) 34 | 35 | print('done') 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /Nanpy/CapacitiveSensorClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_CapacitiveSensor 4 | 5 | #include 6 | #include 7 | #include "CapacitiveSensorClass.h" 8 | 9 | const char* nanpy::CapacitiveSensorClass::get_firmware_id() 10 | { 11 | return "CapacitiveSensor"; 12 | } 13 | 14 | void nanpy::CapacitiveSensorClass::elaborate( nanpy::MethodDescriptor* m ) { 15 | ObjectsManager::elaborate(m); 16 | 17 | if (strcmp(m->getName(), "new") == 0) { 18 | v.insert(new CapacitiveSensor(m->getInt(0), m->getInt(1))); 19 | m->returns(v.getLastIndex()); 20 | } 21 | 22 | if (strcmp(m->getName(), "capacitiveSensor") == 0) { 23 | m->returns(v[m->getObjectId()]->capacitiveSensor(m->getInt(0))); 24 | } 25 | 26 | if (strcmp(m->getName(), "capacitiveSensorRaw") == 0) { 27 | m->returns(v[m->getObjectId()]->capacitiveSensorRaw(m->getInt(0))); 28 | } 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /Nanpy/ColorSensorWrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_ColorSensor 4 | 5 | #include "ColorSensorWrapper.h" 6 | #include 7 | 8 | nanpy::ColorSensorWrapper::ColorSensorWrapper(int s0Pin, int s1Pin, int s2Pin, int s3Pin, int sensorOutPin) { 9 | s0 = s0Pin; 10 | s1 = s1Pin; 11 | s2 = s2Pin; 12 | s3 = s3Pin; 13 | sensorOut = sensorOutPin; 14 | 15 | pinMode(s0, OUTPUT); 16 | pinMode(s1, OUTPUT); 17 | pinMode(s2, OUTPUT); 18 | pinMode(s3, OUTPUT); 19 | pinMode(sensorOut, INPUT); 20 | 21 | digitalWrite(s0, HIGH); 22 | digitalWrite(s1, LOW); 23 | } 24 | 25 | int nanpy::ColorSensorWrapper::getColor(char color) { 26 | if (color == 'r') { 27 | digitalWrite(s2, HIGH); 28 | digitalWrite(s3, LOW); 29 | } else if (color == 'g') { 30 | digitalWrite(s2, HIGH); 31 | digitalWrite(s3, HIGH); 32 | } else if (color == 'b') { 33 | digitalWrite(s2, LOW); 34 | digitalWrite(s3, HIGH); 35 | } 36 | 37 | return pulseIn(sensorOut, LOW); 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Nanpy/DHTClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_DHT 4 | 5 | #include 6 | #include 7 | #include "DHTClass.h" 8 | #include 9 | 10 | const char* nanpy::DHTClass::get_firmware_id() 11 | { 12 | return "DHT"; 13 | } 14 | 15 | void nanpy::DHTClass::elaborate( MethodDescriptor* m ) { 16 | ObjectsManager::elaborate(m); 17 | 18 | if (strcmp(m->getName(),"new") == 0) { 19 | DHT* dht; 20 | if (m->getNArgs() == 3) { 21 | dht = new DHT (m->getInt(0), m->getInt(1), m->getInt(2)); 22 | } else { 23 | dht = new DHT (m->getInt(0), m->getInt(1)); 24 | } 25 | dht->begin(); 26 | v.insert(dht); 27 | m->returns(v.getLastIndex()); 28 | } 29 | 30 | if (strcmp(m->getName(), "readHumidity") == 0) { 31 | m->returns(v[m->getObjectId()]->readHumidity()); 32 | } 33 | 34 | if (strcmp(m->getName(), "readTemperature") == 0) { 35 | m->returns(v[m->getObjectId()]->readTemperature(m->getBool(0))); 36 | } 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Nanpy/RAMClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_RAM 4 | 5 | #include "RAMClass.h" 6 | #include 7 | #include "freeram.h" 8 | 9 | 10 | const char* nanpy::RAMClass::get_firmware_id() 11 | { 12 | return "RAM"; 13 | } 14 | 15 | void nanpy::RAMClass::elaborate( nanpy::MethodDescriptor* m ) { 16 | if (strcmp(m->getName(), "write") == 0) { 17 | uint8_t* p = (uint8_t*)(m->getInt(0)); 18 | *p = m->getInt(1); 19 | m->returns(0); 20 | } 21 | if (strcmp(m->getName(), "read") == 0) { 22 | uint8_t* p = (uint8_t*)(m->getInt(0)); 23 | m->returns(*p); 24 | } 25 | 26 | if (strcmp(m->getName(), "size") == 0) { 27 | #ifdef RAMEND 28 | m->returns(RAMEND+1); 29 | #else 30 | m->returns(0); 31 | #endif 32 | } 33 | 34 | if (strcmp(m->getName(), "free") == 0) { 35 | #ifdef __AVR__ 36 | m->returns(free_ram2()); 37 | #else 38 | m->returns(0); 39 | #endif 40 | } 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /Nanpy/cfg_check.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // check configuration for compatibility 4 | 5 | #ifndef ARDUINO_ARCH_AVR 6 | // disable AVR only features 7 | #define USE_ArduinoCore 0 8 | //#define USE_RAM 0 9 | #define USE_EEPROM 0 10 | #define USE_Register 0 11 | #define USE_Watchdog 0 12 | #define USE_Counter 0 13 | #define USE_DHT 0 14 | #define USE_LiquidCrystal_I2C 0 15 | #define USE_LiquidCrystal 0 16 | #endif 17 | 18 | // check configuration for problems 19 | 20 | #ifdef ARDUINO_ARCH_AVR 21 | #if USE_Tone 22 | # if USE_Counter 23 | # error "USE_Tone conflicts with USE_Counter!" 24 | # endif 25 | #endif 26 | #endif 27 | 28 | #ifdef ESP8266 29 | # define USE_ESP 1 30 | #else 31 | # define USE_ESP 0 32 | #endif 33 | 34 | #ifndef ESP8266 35 | # define USE_WIFI_CONNECTION 0 36 | #endif 37 | 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012-2015 Andrea Stagi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Nanpy/generated_intdefs.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated file, do not edit! 3 | 4 | #define LONGEST_STRING_IN_INTDEFS_H 20 5 | 6 | 7 | #ifdef NUM_DIGITAL_PINS 8 | DEFINE(NUM_DIGITAL_PINS) 9 | #endif 10 | 11 | #ifdef RAMSTART 12 | DEFINE(RAMSTART) 13 | #endif 14 | 15 | #ifdef RAMEND 16 | DEFINE(RAMEND) 17 | #endif 18 | 19 | #ifdef XRAMEND 20 | DEFINE(XRAMEND) 21 | #endif 22 | 23 | #ifdef E2END 24 | DEFINE(E2END) 25 | #endif 26 | 27 | #ifdef FLASHEND 28 | DEFINE(FLASHEND) 29 | #endif 30 | 31 | #ifdef SPM_PAGESIZE 32 | DEFINE(SPM_PAGESIZE) 33 | #endif 34 | 35 | #ifdef E2PAGESIZE 36 | DEFINE(E2PAGESIZE) 37 | #endif 38 | 39 | #ifdef F_CPU 40 | DEFINE(F_CPU) 41 | #endif 42 | 43 | #ifdef ARDUINO 44 | DEFINE(ARDUINO) 45 | #endif 46 | 47 | #ifdef __AVR_LIBC_DATE_ 48 | DEFINE(__AVR_LIBC_DATE_) 49 | #endif 50 | 51 | #ifdef __AVR_LIBC_VERSION__ 52 | DEFINE(__AVR_LIBC_VERSION__) 53 | #endif 54 | 55 | #ifdef IRAM0_ADDR 56 | DEFINE(IRAM0_ADDR) 57 | #endif 58 | 59 | #ifdef IRAM0_SIZE 60 | DEFINE(IRAM0_SIZE) 61 | #endif 62 | 63 | #ifdef IRAM1_ADDR 64 | DEFINE(IRAM1_ADDR) 65 | #endif 66 | 67 | #ifdef IRAM1_SIZE 68 | DEFINE(IRAM1_SIZE) 69 | #endif 70 | -------------------------------------------------------------------------------- /Nanpy/StepperClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Stepper 4 | 5 | #include 6 | #include 7 | #include "StepperClass.h" 8 | #include 9 | 10 | const char* nanpy::StepperClass::get_firmware_id() 11 | { 12 | return "Stepper"; 13 | } 14 | 15 | void nanpy::StepperClass::elaborate( MethodDescriptor* m ) { 16 | ObjectsManager::elaborate(m); 17 | 18 | if (strcmp(m->getName(),"new") == 0) { 19 | int prm = 0; 20 | if (m->getNArgs() == 3) { 21 | v.insert(new Stepper (m->getInt(prm++), m->getInt(prm++), m->getInt(prm++))); 22 | } else { 23 | v.insert(new Stepper (m->getInt(prm++), m->getInt(prm++), m->getInt(prm++), m->getInt(prm++), m->getInt(prm++))); 24 | } 25 | m->returns(v.getLastIndex()); 26 | } 27 | 28 | if (strcmp(m->getName(), "setSpeed") == 0) { 29 | v[m->getObjectId()]->setSpeed(m->getInt(0)); 30 | m->returns(0); 31 | } 32 | 33 | if (strcmp(m->getName(), "step") == 0) { 34 | v[m->getObjectId()]->step(m->getInt(0)); 35 | m->returns(0); 36 | } 37 | } 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Nanpy/ArduinoCoreClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_ArduinoCore 4 | 5 | #include 6 | #include "ArduinoCoreClass.h" 7 | #include 8 | 9 | #define RETURN_PIN_FUNC(x) if (strcmp(m->getName(), #x) == 0) { m->returns(x(m->getInt(0))); } 10 | #define RETURN_PORT_FUNC(x) if (strcmp(m->getName(), #x) == 0) { m->returns((uint32_t)x(m->getInt(0))); } 11 | 12 | const char* nanpy::ArduinoCoreClass::get_firmware_id() 13 | { 14 | return "Core"; 15 | } 16 | 17 | void nanpy::ArduinoCoreClass::elaborate(nanpy::MethodDescriptor* m) 18 | { 19 | RETURN_PIN_FUNC(digitalPinToBitMask); 20 | RETURN_PIN_FUNC(digitalPinToPort); 21 | RETURN_PIN_FUNC(digitalPinToTimer); 22 | 23 | if (strcmp(m->getName(), "analogInPinToBit") == 0) 24 | { 25 | #ifdef analogInPinToBit 26 | m->returns(analogInPinToBit(m->getInt(0))); 27 | #else 28 | m->returns(-1); 29 | #endif 30 | } 31 | // RETURN_PIN_FUNC(analogInPinToBit); 32 | 33 | // if (strcmp(m->getName(), "portModeRegister") == 0) 34 | // { 35 | // m->returns((uint32_t)portModeRegister(m->getInt(0))); 36 | // } 37 | RETURN_PORT_FUNC(portModeRegister); 38 | RETURN_PORT_FUNC(portOutputRegister); 39 | RETURN_PORT_FUNC(portInputRegister); 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Nanpy/MethodDescriptor.h: -------------------------------------------------------------------------------- 1 | #ifndef METHOD_DESCRIPTOR 2 | #define METHOD_DESCRIPTOR 3 | 4 | #include 5 | #include 6 | 7 | namespace nanpy { 8 | class MethodDescriptor { 9 | 10 | private: 11 | char name[50]; 12 | int objid; 13 | char classname[50]; 14 | int n_args; 15 | char **stack; 16 | static char **stack_pool; 17 | static int stack_pool_size; 18 | 19 | public: 20 | MethodDescriptor(); 21 | int getNArgs(); 22 | char* getClass(); 23 | int getObjectId(); 24 | bool getBool(int n); 25 | int getInt(int n); 26 | byte getByte(int n); 27 | float getFloat(int n); 28 | double getDouble(int n); 29 | char* getString(int n); 30 | char* getName(); 31 | void returns(String& val); 32 | void returns(const char* val); 33 | void returns(char val); 34 | void returns(unsigned char val); 35 | void returns(int val); 36 | void returns(unsigned int val); 37 | void returns(float val); 38 | void returns(double val); 39 | void returns(long val); 40 | void returns(unsigned long val); 41 | 42 | }; 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /Nanpy/WatchdogClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Watchdog 4 | 5 | #include 6 | #include "WatchdogClass.h" 7 | #include 8 | #include 9 | 10 | const char* nanpy::WatchdogClass::get_firmware_id() 11 | { 12 | return "Watchdog"; 13 | } 14 | 15 | void nanpy::WatchdogClass::elaborate(nanpy::MethodDescriptor* m) 16 | { 17 | if (strcmp(m->getName(), "reset") == 0) 18 | { 19 | wdt_reset(); 20 | m->returns(0); 21 | } 22 | if (strcmp(m->getName(), "enable") == 0) 23 | { 24 | wdt_enable(m->getInt(0)); 25 | m->returns(0); 26 | } 27 | if (strcmp(m->getName(), "disable") == 0) 28 | { 29 | wdt_disable(); 30 | m->returns(0); 31 | } 32 | } 33 | 34 | #endif 35 | 36 | void disable_watchdog_at_startup() 37 | { 38 | // disable watchdog at startup 39 | // http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html 40 | // "the watchdog timer remains active even after a system reset (except a power-on condition), 41 | // using the fastest prescaler value (approximately 15 ms). 42 | // It is therefore required to turn off the watchdog early during program startup,.." 43 | // "..clearing the watchdog reset flag before disabling the watchdog is required, according to the datasheet." 44 | #ifdef MCUSR 45 | MCUSR = 0; 46 | wdt_disable(); 47 | #endif 48 | } 49 | -------------------------------------------------------------------------------- /codegen/README.md: -------------------------------------------------------------------------------- 1 | Code generation 2 | ================ 3 | 4 | C code is generated for AVR type and registers. 5 | All information is parsed from AVR Libc header files. 6 | 7 | dependencies: 8 | 9 | - path.py 10 | - AVR Libc (http://www.nongnu.org/avr-libc/) 11 | 12 | sudo apt-get install python-pip avr-libc 13 | sudo pip install path.py 14 | 15 | running from project directory: 16 | 17 | python codegen/__init__.py 18 | 19 | generated files: 20 | 21 | - firmware/Nanpy/generated_mcu.h 22 | - firmware/Nanpy/generated_avr_registers.h 23 | 24 | 25 | generated_mcu.h 26 | ----------------- 27 | 28 | This is a list of all known AVR types, "MCU" is defined to the type name. 29 | Example: 30 | 31 | #ifdef __AVR_ATmega328P__ 32 | # ifdef MCU 33 | # error "MCU is already defined" 34 | # endif 35 | # define MCU "__AVR_ATmega328P__" 36 | #endif 37 | 38 | generated_avr_registers.h 39 | --------------------------- 40 | This is a list of all known register names. 41 | Example: 42 | 43 | #ifdef DDRB 44 | DEFINE(DDRB) 45 | #else 46 | MISSING(DDRB) 47 | #endif 48 | 49 | 50 | intdefs 51 | ------- 52 | 53 | Generating int defines list: 54 | 55 | running from project directory: 56 | 57 | python codegen/intdefs.py 58 | 59 | input file: intdefs.txt 60 | generated file: firmware/Nanpy/generated_intdefs.h 61 | 62 | Example: 63 | 64 | #ifdef F_CPU 65 | DEFINE(F_CPU) 66 | #endif 67 | -------------------------------------------------------------------------------- /Nanpy/ServoClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Servo 4 | 5 | #include 6 | #include 7 | #include "ServoClass.h" 8 | #include 9 | 10 | const char* nanpy::ServoClass::get_firmware_id() 11 | { 12 | return "Servo"; 13 | } 14 | 15 | void nanpy::ServoClass::elaborate( nanpy::MethodDescriptor* m ) { 16 | ObjectsManager::elaborate(m); 17 | 18 | if (strcmp(m->getName(),"new") == 0) { 19 | v.insert(new Servo()); 20 | v[v.getLastIndex()]->attach(m->getInt(0)); 21 | m->returns(v.getLastIndex()); 22 | } 23 | 24 | if (strcmp(m->getName(), "write") == 0) { 25 | v[m->getObjectId()]->write(m->getInt(0)); 26 | m->returns(0); 27 | } 28 | 29 | if (strcmp(m->getName(), "read") == 0) { 30 | m->returns(v[m->getObjectId()]->read()); 31 | } 32 | 33 | if (strcmp(m->getName(), "writeMicroseconds") == 0) { 34 | v[m->getObjectId()]->writeMicroseconds(m->getInt(0)); 35 | m->returns(0); 36 | } 37 | 38 | if (strcmp(m->getName(), "readMicroseconds") == 0) { 39 | m->returns(v[m->getObjectId()]->readMicroseconds()); 40 | } 41 | 42 | if (strcmp(m->getName(), "detach") == 0) { 43 | v[m->getObjectId()]->detach(); 44 | m->returns(0); 45 | } 46 | 47 | if (strcmp(m->getName(), "attached") == 0) { 48 | m->returns(v[m->getObjectId()]->attached()); 49 | } 50 | } 51 | 52 | #endif 53 | 54 | -------------------------------------------------------------------------------- /Nanpy/WireClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Wire 4 | 5 | #include 6 | #include 7 | #include "WireClass.h" 8 | #include 9 | 10 | const char* nanpy::WireClass::get_firmware_id() 11 | { 12 | return "Wire"; 13 | } 14 | 15 | void nanpy::WireClass::elaborate( MethodDescriptor* m ) { 16 | 17 | if (strcmp(m->getName(), "begin") == 0) { 18 | if (m->getNArgs()) 19 | { 20 | // slave 21 | Wire.begin(m->getInt(0)); 22 | } 23 | else 24 | { 25 | // master 26 | Wire.begin(); 27 | } 28 | m->returns(0); 29 | } 30 | if (strcmp(m->getName(), "requestFrom") == 0) { 31 | byte x = Wire.requestFrom(m->getInt(0), m->getInt(1), m->getInt(2)); 32 | m->returns(x); 33 | } 34 | if (strcmp(m->getName(), "beginTransmission") == 0) { 35 | Wire.beginTransmission(m->getInt(0)); 36 | m->returns(0); 37 | } 38 | if (strcmp(m->getName(), "endTransmission") == 0) { 39 | byte x = Wire.endTransmission(m->getInt(0)); 40 | m->returns(x); 41 | } 42 | if (strcmp(m->getName(), "write") == 0) { 43 | // string and array writes are not implemented 44 | byte x = Wire.write(m->getInt(0)); 45 | m->returns(x); 46 | } 47 | if (strcmp(m->getName(), "available") == 0) { 48 | int x = Wire.available(); 49 | m->returns(x); 50 | } 51 | if (strcmp(m->getName(), "read") == 0) { 52 | byte x = Wire.read(); 53 | m->returns(x); 54 | } 55 | 56 | // onReceive and onRequest are not implemented 57 | 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /Nanpy/ArduinoClass.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ArduinoClass.h" 3 | #include 4 | 5 | 6 | const char* nanpy::ArduinoClass::get_firmware_id() 7 | { 8 | return "A"; 9 | } 10 | 11 | void nanpy::ArduinoClass::elaborate( nanpy::MethodDescriptor* m ) { 12 | if (strcmp(m->getName(), "dw") == 0) { // digitalWrite 13 | digitalWrite(m->getInt(0), m->getInt(1)); 14 | m->returns(0); 15 | } 16 | 17 | if (strcmp(m->getName(), "r") == 0) { // digitalRead 18 | m->returns(digitalRead(m->getInt(0))); 19 | } 20 | 21 | if (strcmp(m->getName(), "aw") == 0) { // analogWrite 22 | analogWrite(m->getInt(0), m->getInt(1)); 23 | m->returns(0); 24 | } 25 | 26 | if (strcmp(m->getName(), "a") == 0) { // analogRead 27 | m->returns(analogRead(m->getInt(0))); 28 | } 29 | 30 | if (strcmp(m->getName(), "pm") == 0) { // pinMode 31 | pinMode(m->getInt(0), m->getInt(1)); 32 | m->returns(0); 33 | } 34 | 35 | if (strcmp(m->getName(), "delay") == 0) { 36 | m->returns(0); 37 | } 38 | 39 | if (strcmp(m->getName(), "m") == 0) { // millis 40 | m->returns(millis()); 41 | } 42 | 43 | if (strcmp(m->getName(), "pi") == 0) { // pulseIn 44 | pulseIn(m->getInt(0), m->getInt(1)); 45 | m->returns(0); 46 | } 47 | 48 | if (strcmp(m->getName(), "s") == 0) { // shiftOut 49 | // shiftOut(dataPin, clockPin, bitOrder, value) 50 | shiftOut(m->getInt(0), m->getInt(1), m->getInt(2), m->getInt(3)); 51 | m->returns(0); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /Nanpy/UltrasonicWrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Ultrasonic 4 | 5 | #include "UltrasonicWrapper.h" 6 | #include 7 | 8 | nanpy::UltrasonicWrapper::UltrasonicWrapper(int echoPin, int trigPin, bool useInches) { 9 | echo = echoPin; 10 | trig = trigPin; 11 | 12 | if (useInches) { 13 | conversionFactor = 74; 14 | } else { 15 | conversionFactor = 29; 16 | } 17 | 18 | pinMode(echo, INPUT); 19 | pinMode(trig, OUTPUT); 20 | } 21 | 22 | float nanpy::UltrasonicWrapper::getDistance() { 23 | // Code goes here for getDistance() 24 | int duration; 25 | float distance; 26 | 27 | digitalWrite(trig, LOW); 28 | delayMicroseconds(2); 29 | digitalWrite(trig, HIGH); 30 | delayMicroseconds(10); 31 | digitalWrite(trig, LOW); 32 | 33 | // Get the echo pulse that will last the time between the ultrasound signal has been emited and its echo has been received. 34 | duration = pulseIn(echo, HIGH); 35 | // Sound speed throw the air is 343m/s at 20ºC. Given that pulseIn returns microseconds and the pulse has travelled 36 | // twice the distance between the sensor and the blocking object, we have: 37 | // distance (in meters) = duration (in microseconds) x 343 / 1000000 (microseconds per second) / 2 38 | // We are working with distances ranging from 10 to 200 cm so meters are too big for us. We need to work with cm. 39 | // Sound speed will be 34300 cm/s andif we invert that 34300 / 1000000 => 1000000 / 34300 = 29,15... 40 | // we can express the same formula as: 41 | // distance (in centimeters) = duration (in microseconds) / 29 / 2 that is much simpler and faster to compute. 42 | 43 | distance = duration / conversionFactor / 2; 44 | 45 | return distance; 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /Nanpy/LiquidCrystalClass_I2C.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_LiquidCrystal_I2C 4 | 5 | #include 6 | #include 7 | #include "LiquidCrystalClass_I2C.h" 8 | #include 9 | #include 10 | 11 | const char* nanpy::LiquidCrystalClass_I2C::get_firmware_id() 12 | { 13 | return "Lcd_I2C"; 14 | } 15 | 16 | void nanpy::LiquidCrystalClass_I2C::elaborate( nanpy::MethodDescriptor* m ) { 17 | ObjectsManager::elaborate(m); 18 | 19 | if (strcmp(m->getName(), "new") == 0) { 20 | int prm = 0; 21 | // lcd_Addr, En, Rw, Rs, d4, d5, d6, d7 22 | v.insert(new LiquidCrystal_I2C ( 23 | m->getInt(prm++), 24 | m->getInt(prm++), 25 | m->getInt(prm++), 26 | m->getInt(prm++), 27 | m->getInt(prm++), 28 | m->getInt(prm++), 29 | m->getInt(prm++), 30 | m->getInt(prm++), 31 | m->getInt(prm++), 32 | (t_backlighPol)m->getInt(prm++))); 33 | v[m->getObjectId()]->begin(m->getInt(prm++), m->getInt(prm++)); 34 | m->returns(v.getLastIndex()); 35 | } 36 | 37 | if (strcmp(m->getName(), "printString") == 0) { 38 | if(m->getNArgs() == 3) { 39 | v[m->getObjectId()]->setCursor(m->getInt(1), m->getInt(2)); 40 | v[m->getObjectId()]->print(m->getString(0)); 41 | } 42 | else 43 | v[m->getObjectId()]->print(m->getString(0)); 44 | m->returns(0); 45 | } 46 | 47 | if (strcmp(m->getName(), "setCursor") == 0) { 48 | v[m->getObjectId()]->setCursor(m->getInt(0), m->getInt(1)); 49 | m->returns(0); 50 | } 51 | 52 | if (strcmp(m->getName(), "setBacklight") == 0) { 53 | v[m->getObjectId()]->setBacklight(m->getInt(0)); 54 | m->returns(0); 55 | } 56 | }; 57 | #endif 58 | -------------------------------------------------------------------------------- /Nanpy/BaseClass.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE_CLASS 2 | #define BASE_CLASS 3 | 4 | #include "cfg_all.h" 5 | #include "SlimArray.h" 6 | #include "MethodDescriptor.h" 7 | 8 | namespace nanpy { 9 | 10 | class BaseClass { 11 | 12 | public: 13 | virtual void elaborate( nanpy::MethodDescriptor* m ) = 0; 14 | virtual const char* get_firmware_id() = 0; 15 | 16 | }; 17 | 18 | template class ObjectsManager : public BaseClass { 19 | 20 | protected: 21 | nanpy::SlimArray v; 22 | 23 | public: 24 | ObjectsManager() {} 25 | void elaborate( nanpy::MethodDescriptor* m ) { 26 | if (strcmp(m->getName(), "remove") == 0) { 27 | delete(v[m->getObjectId()]); 28 | v.remove(m->getObjectId()); 29 | COMM_SERIAL.println("0"); 30 | } 31 | } 32 | 33 | }; 34 | 35 | 36 | class Register { 37 | static nanpy::SlimArray classes; 38 | 39 | public: 40 | 41 | template static void registerClass() { 42 | nanpy::BaseClass* obj = (nanpy::BaseClass*)new T(); 43 | classes.insert(obj); 44 | } 45 | 46 | static nanpy::SlimArray * get_classes() { 47 | return &classes; 48 | } 49 | 50 | static void elaborate(nanpy::MethodDescriptor* m) { 51 | for(int i = 0 ; i < classes.getSize() ; i++) 52 | { 53 | if (strcmp(m->getClass(), classes[i]->get_firmware_id()) == 0) 54 | { 55 | classes[i]->elaborate(m); 56 | } 57 | } 58 | 59 | if(m != NULL) { 60 | delete(m); 61 | m = NULL; 62 | } 63 | } 64 | 65 | }; 66 | } 67 | 68 | #define REGISTER_CLASS_CONDITIONAL(cls, condition) if(condition) Register::registerClass(); 69 | #define REGISTER_CLASS(cls) REGISTER_CLASS_CONDITIONAL(cls, 1); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /Nanpy/cfg_defaults.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // default configuration 4 | 5 | // All these settings can be overwritten in cfg.h 6 | 7 | #ifndef COMM_SERIAL 8 | # define COMM_SERIAL Serial 9 | #endif 10 | 11 | #ifndef USE_WIFI_CONNECTION 12 | # define USE_WIFI_CONNECTION 0 13 | #endif 14 | 15 | #ifndef BAUDRATE 16 | # define BAUDRATE 115200 17 | #endif 18 | 19 | #ifndef USE_Servo 20 | # define USE_Servo 0 21 | #endif 22 | 23 | #ifndef USE_Tone 24 | # define USE_Tone 0 25 | #endif 26 | 27 | #ifndef USE_LiquidCrystal 28 | # define USE_LiquidCrystal 0 29 | #endif 30 | 31 | #ifndef USE_Stepper 32 | # define USE_Stepper 0 33 | #endif 34 | 35 | #ifndef USE_EEPROM 36 | # define USE_EEPROM 0 37 | #endif 38 | 39 | #ifndef USE_RAM 40 | # define USE_RAM 0 41 | #endif 42 | 43 | #ifndef USE_Define 44 | # define USE_Define 0 45 | #endif 46 | 47 | #ifndef USE_ArduinoCore 48 | # define USE_ArduinoCore 0 49 | #endif 50 | 51 | #ifndef USE_Watchdog 52 | # define USE_Watchdog 0 53 | #endif 54 | 55 | #ifndef USE_Register 56 | # define USE_Register 0 57 | #endif 58 | 59 | #ifndef USE_Info 60 | # define USE_Info 0 61 | #endif 62 | 63 | #ifndef USE_Counter 64 | # define USE_Counter 0 65 | #endif 66 | 67 | #ifndef USE_Wire 68 | # define USE_Wire 0 69 | #endif 70 | 71 | #ifndef USE_OneWire 72 | # define USE_OneWire 0 73 | #endif 74 | 75 | #ifndef USE_DallasTemperature 76 | # define USE_DallasTemperature 0 77 | #endif 78 | 79 | #ifndef USE_CapacitiveSensor 80 | # define USE_CapacitiveSensor 0 81 | #endif 82 | 83 | #ifndef USE_DHT 84 | # define USE_DHT 0 85 | #endif 86 | 87 | #ifndef USE_LiquidCrystal_I2C 88 | # define USE_LiquidCrystal_I2C 0 89 | #endif 90 | 91 | #ifndef USE_TLC5947 92 | # define USE_TLC5947 0 93 | #endif 94 | 95 | #ifndef USE_MCP41xxx 96 | # define USE_MCP41xxx 0 97 | #endif 98 | 99 | #ifndef USE_Ultrasonic 100 | # define USE_Ultrasonic 0 101 | #endif 102 | 103 | #ifndef USE_ColorSensor 104 | # define USE_ColorSensor 0 105 | #endif 106 | -------------------------------------------------------------------------------- /Nanpy/freeram.c: -------------------------------------------------------------------------------- 1 | #if defined(__AVR__) 2 | #include 3 | #include 4 | 5 | 6 | extern unsigned int __bss_end; 7 | extern unsigned int __heap_start; 8 | extern void *__brkval; 9 | extern unsigned int __data_start; 10 | 11 | /// return available RAM 12 | int free_ram1() 13 | { 14 | /// copy from http://arduino.cc/playground/Code/AvailableMemory 15 | int free_memory; 16 | 17 | if ((int) __brkval == 0) 18 | free_memory = ((int) &free_memory) - ((int) &__bss_end); 19 | else 20 | free_memory = ((int) &free_memory) - ((int) __brkval); 21 | 22 | return free_memory; 23 | } 24 | 25 | /// return available RAM 26 | /*! This function places the current value of the heap and stack pointers in the 27 | * variables. You can call it from any place in your code and save the data for 28 | * outputting or displaying later. This allows you to check at different parts of 29 | * your program flow. 30 | * The stack pointer starts at the top of RAM and grows downwards. The heap pointer 31 | * starts just above the static variables etc. and grows upwards. SP should always 32 | * be larger than HP or you'll be in big trouble! The smaller the gap, the more 33 | * careful you need to be. Julian Gall 6-Feb-2009. 34 | */ 35 | int free_ram2() 36 | { 37 | /// copy from http://arduino.cc/playground/Code/AvailableMemory 38 | uint8_t * heapptr, *stackptr; 39 | 40 | stackptr = (uint8_t *) malloc(4); // use stackptr temporarily 41 | heapptr = stackptr; // save value of heap pointer 42 | free(stackptr); // free up the memory again (sets stackptr to 0) 43 | stackptr = (uint8_t *) (SP); // save value of stack pointer 44 | return (int) (stackptr - heapptr); 45 | } 46 | 47 | /// return available RAM 48 | 49 | /// this function will return the number of bytes currently free in RAM 50 | /// written by David A. Mellis 51 | /// based on code by Rob Faludi http://www.faludi.com 52 | int free_ram3() 53 | { 54 | /// copy from http://arduino.cc/playground/Code/AvailableMemory 55 | int size = (int) RAMEND - (int) &__data_start; 56 | uint8_t *buf; 57 | 58 | while ((buf = (uint8_t *) malloc(--size)) == NULL) 59 | ; 60 | 61 | free(buf); 62 | 63 | return size; 64 | } 65 | #endif -------------------------------------------------------------------------------- /Nanpy/OneWireClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_OneWire 4 | 5 | #include 6 | #include "OneWireClass.h" 7 | #include 8 | 9 | const char* nanpy::OneWireClass::get_firmware_id() 10 | { 11 | return "OneWire"; 12 | } 13 | 14 | void nanpy::OneWireClass::elaborate( nanpy::MethodDescriptor* m ) { 15 | ObjectsManager::elaborate(m); 16 | 17 | if (strcmp(m->getName(), "new") == 0) { 18 | v.insert(new OneWire(m->getInt(0))); 19 | m->returns(v.getLastIndex()); 20 | } 21 | 22 | if (strcmp(m->getName(), "search") == 0) { 23 | byte addr[8]; 24 | int res = v[m->getObjectId()]->search(addr); 25 | 26 | if(!res) { 27 | v[m->getObjectId()]->reset_search(); 28 | delay(250); 29 | m->returns(1); 30 | } 31 | 32 | else { 33 | String addr_hex = String(); 34 | for( int cc = 0; cc < 7; cc++ ) 35 | addr_hex += String(addr[cc]) + " "; 36 | addr_hex += String(addr[7]); 37 | m->returns(addr_hex); 38 | } 39 | } 40 | 41 | if (strcmp(m->getName(), "reset_search") == 0) { 42 | v[m->getObjectId()]->reset_search(); 43 | m->returns(0); 44 | } 45 | 46 | if (strcmp(m->getName(), "reset") == 0) { 47 | m->returns(v[m->getObjectId()]->reset()); 48 | } 49 | 50 | if (strcmp(m->getName(), "select") == 0) { 51 | byte* addr = (byte*)malloc(m->getNArgs() * sizeof(byte)); 52 | 53 | for(int i = 0 ; i < m->getNArgs() ; i++) { 54 | addr[i] = m->getByte(i); 55 | } 56 | 57 | v[m->getObjectId()]->select(addr); 58 | 59 | delete(addr); 60 | m->returns(0); 61 | } 62 | 63 | if (strcmp(m->getName(), "write") == 0) { 64 | if(m->getNArgs() == 1) 65 | v[m->getObjectId()]->write(m->getInt(0)); 66 | else 67 | v[m->getObjectId()]->write(m->getInt(0), m->getInt(1)); 68 | m->returns(0); 69 | } 70 | 71 | if (strcmp(m->getName(), "read") == 0) { 72 | m->returns(v[m->getObjectId()]->read()); 73 | } 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /Nanpy/LiquidCrystalClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_LiquidCrystal 4 | 5 | #include 6 | #include 7 | #include "LiquidCrystalClass.h" 8 | #include 9 | #include 10 | 11 | const char* nanpy::LiquidCrystalClass::get_firmware_id() 12 | { 13 | return "Lcd"; 14 | } 15 | 16 | void nanpy::LiquidCrystalClass::elaborate( nanpy::MethodDescriptor* m ) { 17 | ObjectsManager::elaborate(m); 18 | 19 | if (strcmp(m->getName(), "new") == 0) { 20 | int prm = 0; 21 | v.insert(new LiquidCrystal (m->getInt(prm++), m->getInt(prm++), 22 | m->getInt(prm++), m->getInt(prm++), m->getInt(prm++), m->getInt(prm++))); 23 | v[m->getObjectId()]->begin(m->getInt(prm++), m->getInt(prm++)); 24 | m->returns(v.getLastIndex()); 25 | } 26 | 27 | if (strcmp(m->getName(), "printString") == 0) { 28 | if(m->getNArgs() == 3) { 29 | v[m->getObjectId()]->setCursor(m->getInt(1), m->getInt(2)); 30 | v[m->getObjectId()]->print(m->getString(0)); 31 | } 32 | else 33 | v[m->getObjectId()]->print(m->getString(0)); 34 | m->returns(0); 35 | } 36 | 37 | if (strcmp(m->getName(), "setCursor") == 0) { 38 | v[m->getObjectId()]->setCursor(m->getInt(0), m->getInt(1)); 39 | m->returns(0); 40 | } 41 | 42 | if (strcmp(m->getName(), "autoscroll") == 0) { 43 | v[m->getObjectId()]->autoscroll(); 44 | m->returns(0); 45 | } 46 | 47 | if (strcmp(m->getName(), "noAutoscroll") == 0) { 48 | v[m->getObjectId()]->noAutoscroll(); 49 | m->returns(0); 50 | } 51 | 52 | if (strcmp(m->getName(), "clear") == 0) { 53 | v[m->getObjectId()]->clear(); 54 | m->returns(0); 55 | } 56 | 57 | if (strcmp(m->getName(), "createChar") == 0) { 58 | byte chr[8]; 59 | for(int i = 0; i < 8; i++) { 60 | chr[i] = m->getByte(i+1); 61 | } 62 | v[m->getObjectId()]->createChar(m->getByte(0), chr); 63 | m->returns(0); 64 | } 65 | 66 | if (strcmp(m->getName(), "write") == 0) { 67 | v[m->getObjectId()]->write(m->getByte(0)); 68 | m->returns(0); 69 | } 70 | }; 71 | #endif 72 | -------------------------------------------------------------------------------- /tests/test_build.py: -------------------------------------------------------------------------------- 1 | from nose.tools import eq_, ok_ 2 | from path import Path 3 | from pyavrutils.arduino import Arduino, ArduinoCompileError 4 | from pyavrutils.support import simple_targets 5 | import logging 6 | from nose_ittr import IttrMultiplier, ittr 7 | import tempfile 8 | 9 | root = Path(__file__).abspath().parent.parent 10 | sample_cfg = root / 'sample_cfg.h' 11 | 12 | ''' 13 | sudo rm -f /usr/share/arduino/libraries/Robot_Control/Wire.h 14 | ''' 15 | 16 | EXTERNAL_LIBS = [ 17 | 'USE_LiquidCrystal_I2C', 18 | 'USE_OneWire', 19 | 'USE_DallasTemperature', 20 | 'USE_CapacitiveSensor', 21 | 'USE_DHT', 22 | 'USE_TLC5947', 23 | 'USE_MCP41xxx' 24 | ] 25 | 26 | MCUs = [ 27 | # 'atmega8', 28 | # 'atmega48', 29 | 'atmega168', 30 | 'atmega328p', 31 | # 'atmega640', 32 | 'atmega1280', 33 | 'atmega2560' 34 | ] 35 | 36 | 37 | def tmpdir(dir=None, suffix=''): 38 | x = tempfile.mkdtemp(suffix=suffix, prefix='nanpy_', dir=dir) 39 | return Path(x) 40 | 41 | 42 | def get_features(): 43 | ls = [] 44 | print 'reading', sample_cfg 45 | for l in sample_cfg.lines(): 46 | parts = l.split() 47 | if len(parts) >= 3: 48 | if parts[0] == '#define': 49 | s = parts[1] 50 | if s.startswith('USE'): 51 | if not s.endswith('CONNECTION'): 52 | ls.append(s) 53 | assert len(ls) > 3 54 | print 'get_features:', ls 55 | return ls 56 | 57 | FEATURES = [f for f in get_features() if f not in EXTERNAL_LIBS] 58 | 59 | 60 | def test_config(): 61 | known_mcus = [t.mcu for t in simple_targets()] 62 | for mcu in MCUs: 63 | assert mcu in known_mcus, 'MCU %s was not found in config %s' % ( 64 | mcu, known_mcus) 65 | 66 | 67 | class TestFoo(object): 68 | __metaclass__ = IttrMultiplier 69 | 70 | @ittr(mcu=MCUs, feature=FEATURES) 71 | def test_build(self): 72 | tdir = tmpdir() 73 | try: 74 | 75 | f = self.feature 76 | scfg = '#define %s 1' % f 77 | 78 | (root / 'Nanpy').copytree(tdir / 'Nanpy') 79 | ino = tdir / 'Nanpy' / 'Nanpy.ino' 80 | cfg = tdir / 'Nanpy' / 'cfg.h' 81 | 82 | cfg.write_text(scfg) 83 | 84 | cc = Arduino(mcu=self.mcu) 85 | print cc.mcu, ino 86 | cc.build(ino) 87 | ok_(cc.size().ok) 88 | finally: 89 | tdir.rmtree() 90 | -------------------------------------------------------------------------------- /Nanpy/SlimArray.h: -------------------------------------------------------------------------------- 1 | #ifndef SLIM_ARRAY 2 | #define SLIM_ARRAY 3 | 4 | #include 5 | 6 | namespace nanpy { 7 | template class SlimArray { 8 | 9 | private: 10 | 11 | int size; 12 | int cur_size; 13 | T *v; 14 | 15 | public: 16 | 17 | SlimArray(int s=0) : size(s), v((T*)malloc(sizeof(T) * size)) { 18 | for(int i = 0; i < size; i++) 19 | v[i] = 0; 20 | cur_size = 0; 21 | } 22 | 23 | SlimArray(T *x, int s) : size(s), v((T*)malloc(sizeof(T) * size)) { 24 | size = s; 25 | for(int i = 0; i < size; i++) 26 | v[i] = x[i]; 27 | } 28 | 29 | void insert(T el) { 30 | this->insert(cur_size, el); 31 | } 32 | 33 | void remove(int pos) { 34 | if(pos > size - 1) 35 | return; 36 | 37 | T* newv = (T*)malloc(sizeof(T) * (size - 1)); 38 | 39 | int j = 0; 40 | 41 | for(int i = 0; i < size; i++) { 42 | if(i != pos) { 43 | newv[j] = v[i]; 44 | j++; 45 | } 46 | } 47 | 48 | free(v); 49 | v = newv; 50 | cur_size--; 51 | size--; 52 | } 53 | 54 | void insert(int pos, T el) { 55 | if(pos > size - 1) { 56 | T* newv = (T*)malloc(sizeof(T) * (pos + 1)); 57 | newv[pos] = el; 58 | for(int i = 0; i < size; i++) 59 | newv[i] = v[i]; 60 | free(v); 61 | size = pos + 1; 62 | v = newv; 63 | } else { 64 | v[pos] = el; 65 | } 66 | cur_size++; 67 | } 68 | 69 | T get(int pos) { 70 | return v[pos]; 71 | } 72 | 73 | T& operator[] ( int pos ) { 74 | return v[pos]; 75 | } 76 | 77 | int getSize() { 78 | return this->size; 79 | } 80 | 81 | int getLastIndex() { 82 | return (this->cur_size - 1); 83 | } 84 | 85 | ~SlimArray() { 86 | free(v); 87 | } 88 | 89 | }; 90 | } 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /Nanpy/ToneClass.h: -------------------------------------------------------------------------------- 1 | #ifndef TONE_CLASS 2 | #define TONE_CLASS 3 | 4 | #include "BaseClass.h" 5 | #include "MethodDescriptor.h" 6 | 7 | #define NOTE_B0 31 8 | #define NOTE_C1 33 9 | #define NOTE_CS1 35 10 | #define NOTE_D1 37 11 | #define NOTE_DS1 39 12 | #define NOTE_E1 41 13 | #define NOTE_F1 44 14 | #define NOTE_FS1 46 15 | #define NOTE_G1 49 16 | #define NOTE_GS1 52 17 | #define NOTE_A1 55 18 | #define NOTE_AS1 58 19 | #define NOTE_B1 62 20 | #define NOTE_C2 65 21 | #define NOTE_CS2 69 22 | #define NOTE_D2 73 23 | #define NOTE_DS2 78 24 | #define NOTE_E2 82 25 | #define NOTE_F2 87 26 | #define NOTE_FS2 93 27 | #define NOTE_G2 98 28 | #define NOTE_GS2 104 29 | #define NOTE_A2 110 30 | #define NOTE_AS2 117 31 | #define NOTE_B2 123 32 | #define NOTE_C3 131 33 | #define NOTE_CS3 139 34 | #define NOTE_D3 147 35 | #define NOTE_DS3 156 36 | #define NOTE_E3 165 37 | #define NOTE_F3 175 38 | #define NOTE_FS3 185 39 | #define NOTE_G3 196 40 | #define NOTE_GS3 208 41 | #define NOTE_A3 220 42 | #define NOTE_AS3 233 43 | #define NOTE_B3 247 44 | #define NOTE_C4 262 45 | #define NOTE_CS4 277 46 | #define NOTE_D4 294 47 | #define NOTE_DS4 311 48 | #define NOTE_E4 330 49 | #define NOTE_F4 349 50 | #define NOTE_FS4 370 51 | #define NOTE_G4 392 52 | #define NOTE_GS4 415 53 | #define NOTE_A4 440 54 | #define NOTE_AS4 466 55 | #define NOTE_B4 494 56 | #define NOTE_C5 523 57 | #define NOTE_CS5 554 58 | #define NOTE_D5 587 59 | #define NOTE_DS5 622 60 | #define NOTE_E5 659 61 | #define NOTE_F5 698 62 | #define NOTE_FS5 740 63 | #define NOTE_G5 784 64 | #define NOTE_GS5 831 65 | #define NOTE_A5 880 66 | #define NOTE_AS5 932 67 | #define NOTE_B5 988 68 | #define NOTE_C6 1047 69 | #define NOTE_CS6 1109 70 | #define NOTE_D6 1175 71 | #define NOTE_DS6 1245 72 | #define NOTE_E6 1319 73 | #define NOTE_F6 1397 74 | #define NOTE_FS6 1480 75 | #define NOTE_G6 1568 76 | #define NOTE_GS6 1661 77 | #define NOTE_A6 1760 78 | #define NOTE_AS6 1865 79 | #define NOTE_B6 1976 80 | #define NOTE_C7 2093 81 | #define NOTE_CS7 2217 82 | #define NOTE_D7 2349 83 | #define NOTE_DS7 2489 84 | #define NOTE_E7 2637 85 | #define NOTE_F7 2794 86 | #define NOTE_FS7 2960 87 | #define NOTE_G7 3136 88 | #define NOTE_GS7 3322 89 | #define NOTE_A7 3520 90 | #define NOTE_AS7 3729 91 | #define NOTE_B7 3951 92 | #define NOTE_C8 4186 93 | #define NOTE_CS8 4435 94 | #define NOTE_D8 4699 95 | #define NOTE_DS8 4978 96 | 97 | #include "ToneWrapper.h" 98 | 99 | namespace nanpy { 100 | 101 | class ToneClass: public ObjectsManager { 102 | 103 | public: 104 | void elaborate( nanpy::MethodDescriptor* m ); 105 | const char* get_firmware_id(); 106 | 107 | }; 108 | } 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /sample_cfg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | // only for ESP8266 5 | #define USE_WIFI_CONNECTION 0 6 | 7 | // for WIFI connection 8 | #define WIFI_SSID "***" 9 | #define WIFI_PASSWORD "***" 10 | 11 | 12 | // for serial connection 13 | #define BAUDRATE 115200 14 | #define COMM_SERIAL Serial 15 | 16 | // info about existence of other features 17 | #define USE_Info 1 18 | 19 | // definitions: MCU type, frequency, Arduino version, 20 | // EEPROM size, RAM size, pin count, build time,.. 21 | #define USE_Define 1 22 | 23 | // low level mapping of pins and ports 24 | #define USE_ArduinoCore 1 25 | 26 | // read, write RAM 27 | #define USE_RAM 1 28 | 29 | // read, write EEPROM 30 | #define USE_EEPROM 1 31 | 32 | // read, write AVR registers 33 | #define USE_Register 0 34 | 35 | // watchdog and reset 36 | #define USE_Watchdog 0 37 | 38 | #define USE_Tone 0 39 | 40 | #define USE_LiquidCrystal 0 41 | 42 | // I2C 43 | #define USE_Wire 0 44 | 45 | #define USE_Servo 0 46 | 47 | #define USE_Stepper 0 48 | 49 | // frequency counter, USE_Tone should be off! 50 | #define USE_Counter 0 51 | 52 | // GW Robotics Classes 53 | #define USE_Ultrasonic 0 54 | #define USE_ColorSensor 0 55 | 56 | /////////////////////////////////////////////////////////////////////// 57 | // external libraries should be installed for the following features: 58 | /////////////////////////////////////////////////////////////////////// 59 | 60 | // install with Library Manager: "OneWire" 61 | // https://github.com/PaulStoffregen/OneWire 62 | #define USE_OneWire 0 63 | 64 | // install with Library Manager: "DallasTemperature" 65 | // https://github.com/milesburton/Arduino-Temperature-Control-Library 66 | #define USE_DallasTemperature 0 67 | 68 | 69 | // install with Library Manager: "CapacitiveSensor" 70 | // https://github.com/PaulStoffregen/CapacitiveSensor 71 | #define USE_CapacitiveSensor 0 72 | 73 | // install with Library Manager: "DHT sensor library","Adafruit Unified Sensor" 74 | // https://github.com/adafruit/DHT-sensor-library 75 | #define USE_DHT 0 76 | 77 | // https://bitbucket.org/fmalpartida/new-liquidcrystal 78 | #define USE_LiquidCrystal_I2C 0 79 | 80 | // install with Library Manager: "Adafruit TLC5947" 81 | // https://github.com/adafruit/Adafruit_TLC5947 82 | #define USE_TLC5947 0 83 | 84 | // install with Library Manager: "MCP41XXX" 85 | // https://github.com/ArduinoMax/MCP41xxx 86 | #define USE_MCP41xxx 0 87 | -------------------------------------------------------------------------------- /Nanpy/RegisterClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Register 4 | 5 | #include 6 | #include "RegisterClass.h" 7 | #include 8 | 9 | // http://www.nongnu.org/avr-libc/user-manual/pgmspace.html 10 | 11 | #define MISSING(x) 12 | 13 | // example: 14 | // char string_OCR2A[] PROGMEM = "OCR2A"; 15 | #define DEFINE(x) const char string_##x[] PROGMEM = #x; 16 | #include "generated_avr_registers.h" 17 | #undef DEFINE 18 | 19 | const char * const name_table[] PROGMEM = 20 | { 21 | // example: 22 | // string_OCR2A, 23 | #define DEFINE(x) string_##x, 24 | #include "generated_avr_registers.h" 25 | #undef DEFINE 26 | }; 27 | 28 | #define DEFINE(x) (uint16_t)(&x), 29 | const uint16_t reg_list[] PROGMEM = 30 | { 31 | #include "generated_avr_registers.h" 32 | }; 33 | #undef DEFINE 34 | 35 | #define DEFINE(x) sizeof(x), 36 | const uint16_t sizeof_list[] PROGMEM = 37 | { 38 | #include "generated_avr_registers.h" 39 | }; 40 | #undef DEFINE 41 | 42 | const int REG_COUNT = sizeof(sizeof_list) / sizeof(sizeof_list[0]); 43 | 44 | #define LONGEST_REGISTER_NAME 21 45 | 46 | const char* nanpy::RegisterClass::get_firmware_id() 47 | { 48 | return "R"; 49 | } 50 | 51 | void nanpy::RegisterClass::elaborate(nanpy::MethodDescriptor* m) 52 | { 53 | if (strcmp(m->getName(), "c") == 0) // count 54 | { 55 | m->returns(REG_COUNT); 56 | } 57 | else if (strcmp(m->getName(), "n") == 0) // name 58 | { 59 | word regindex = m->getInt(0); 60 | char buffer[LONGEST_REGISTER_NAME]; 61 | strcpy_P(buffer, (PGM_P) pgm_read_word(&(name_table[regindex]))); 62 | m->returns(buffer); 63 | } 64 | else 65 | { 66 | word regindex = m->getInt(0); 67 | word regvalue = m->getInt(1); 68 | 69 | word regaddr = pgm_read_word(®_list[regindex]); 70 | byte regsize = pgm_read_byte(&sizeof_list[regindex]); 71 | 72 | volatile byte* preg8 = (volatile byte*) regaddr; 73 | volatile word* preg16 = (volatile word*) regaddr; 74 | 75 | if (strcmp(m->getName(), "r") == 0) // read 76 | { 77 | switch (regsize) 78 | { 79 | case 1: 80 | m->returns(*preg8); 81 | break; 82 | case 2: 83 | m->returns(*preg16); 84 | break; 85 | } 86 | } 87 | else if (strcmp(m->getName(), "w") == 0) // write 88 | { 89 | switch (regsize) 90 | { 91 | case 1: 92 | *preg8 = (byte) regvalue; 93 | break; 94 | case 2: 95 | *preg16 = regvalue; 96 | break; 97 | } 98 | m->returns(0); 99 | } 100 | else if (strcmp(m->getName(), "a") == 0) // address 101 | { 102 | m->returns(regaddr); 103 | } 104 | else if (strcmp(m->getName(), "s") == 0) // size 105 | { 106 | m->returns(regsize); 107 | } 108 | 109 | } 110 | } 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /Nanpy/FreqCount.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* FreqCount Library, for measuring frequencies 3 | * http://www.pjrc.com/teensy/td_libs_FreqCount.html 4 | * Copyright (c) 2011 PJRC.COM, LLC - Paul Stoffregen 5 | * 6 | * Version 1.0 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | // FreqCount Library was so modified that it can be included in Nanpy 28 | 29 | #include "cfg_all.h" 30 | #if USE_Counter 31 | 32 | #include "FreqCount.h" 33 | #include "timers.h" 34 | 35 | static uint16_t count_msw; 36 | static uint32_t count_prev; 37 | static volatile uint32_t count_output; 38 | static volatile uint8_t count_ready; 39 | static uint16_t gate_length; 40 | static uint16_t gate_index; 41 | 42 | 43 | void FreqCountClass::begin(uint16_t msec) 44 | { 45 | if (msec < 10) return; 46 | gate_index = 0; 47 | count_msw = 0; 48 | count_prev = 0; 49 | count_ready = 0; 50 | counter_init(); 51 | gate_length = timer_init(msec); 52 | uint8_t status = SREG; 53 | cli(); 54 | timer_start(); 55 | timer_isr_latency_delay(); 56 | counter_start(); 57 | SREG = status; 58 | } 59 | 60 | uint8_t FreqCountClass::available(void) 61 | { 62 | return count_ready; 63 | } 64 | 65 | uint32_t FreqCountClass::read(void) 66 | { 67 | uint32_t count; 68 | uint8_t status; 69 | 70 | status = SREG; 71 | cli(); 72 | count = count_output; 73 | count_ready = 0; 74 | SREG = status; 75 | return count; 76 | } 77 | 78 | void FreqCountClass::end(void) 79 | { 80 | timer_shutdown(); 81 | counter_shutdown(); 82 | } 83 | 84 | 85 | ISR(TIMER_ISR_VECTOR) 86 | { 87 | uint16_t count_lsw; 88 | uint32_t count; 89 | uint16_t index, length; 90 | 91 | count_lsw = counter_read(); 92 | if (counter_overflow()) { 93 | counter_overflow_reset(); 94 | count_msw++; 95 | } 96 | index = gate_index + 1; 97 | length = gate_length; 98 | if (index >= length) { 99 | gate_index = 0; 100 | count = ((uint32_t)count_msw << 16) + count_lsw; 101 | count_output = count - count_prev; 102 | count_prev = count; 103 | count_ready = 1; 104 | restore_other_interrupts(); 105 | } else { 106 | if (index == length - 1) disable_other_interrupts(); 107 | gate_index = index; 108 | } 109 | } 110 | 111 | 112 | FreqCountClass FreqCount; 113 | 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /Nanpy/DefineClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_Define 4 | 5 | #include 6 | #include "DefineClass.h" 7 | #include 8 | 9 | #include "generated_mcu.h" 10 | #ifndef MCU 11 | // unknown MCU 12 | # define MCU "" 13 | #endif 14 | 15 | #ifdef ARDUINO_ARCH_AVR 16 | # define USE_PGM 17 | #endif 18 | 19 | #ifdef USE_PGM 20 | # define MY_PROGMEM PROGMEM 21 | #else 22 | # define MY_PROGMEM 23 | #endif 24 | 25 | 26 | // http://www.nongnu.org/avr-libc/user-manual/pgmspace.html 27 | 28 | // example: 29 | // char string_A0[] PROGMEM = "A0"; 30 | #define DEFINE(x) const char string_##x[] MY_PROGMEM = #x; 31 | #include "generated_intdefs.h" 32 | #include "intdefs.h" 33 | #undef DEFINE 34 | 35 | const char * const name_table[] MY_PROGMEM = 36 | { 37 | // example: 38 | // string_A0, 39 | #define DEFINE(x) string_##x, 40 | #include "generated_intdefs.h" 41 | #include "intdefs.h" 42 | #undef DEFINE 43 | }; 44 | 45 | const int32_t value_table[] MY_PROGMEM = 46 | { 47 | // example: 48 | // A0, 49 | #define DEFINE(x) x, 50 | #include "generated_intdefs.h" 51 | #include "intdefs.h" 52 | #undef DEFINE 53 | }; 54 | 55 | 56 | #define COUNT_INT_DEFS sizeof(name_table)/sizeof(name_table[0]) 57 | 58 | #define COUNT_STR_DEFS 4 59 | // __TIME__, __DATE__, __VERSION__, MCU 60 | 61 | const char* nanpy::DefineClass::get_firmware_id() 62 | { 63 | return "D"; 64 | } 65 | 66 | void nanpy::DefineClass::elaborate(nanpy::MethodDescriptor* m) 67 | { 68 | if (strcmp(m->getName(), "c") == 0) // count 69 | { 70 | m->returns(COUNT_INT_DEFS + COUNT_STR_DEFS); 71 | } 72 | if (strcmp(m->getName(), "n") == 0) // name 73 | { 74 | int index = m->getInt(0); 75 | switch (index) 76 | { 77 | case COUNT_INT_DEFS + 0: 78 | m->returns("__TIME__"); 79 | break; 80 | case COUNT_INT_DEFS + 1: 81 | m->returns("__DATE__"); 82 | break; 83 | case COUNT_INT_DEFS + 2: 84 | m->returns("__VERSION__"); 85 | break; 86 | case COUNT_INT_DEFS + 3: 87 | m->returns("MCU"); 88 | break; 89 | 90 | default: 91 | char buffer[LONGEST_STRING_IN_INTDEFS_H+1]; 92 | #ifdef USE_PGM 93 | strcpy_P(buffer, (PGM_P) pgm_read_word(&(name_table[index]))); 94 | #else 95 | strcpy(buffer, name_table[index]); 96 | #endif 97 | m->returns(buffer); 98 | } 99 | } 100 | if (strcmp(m->getName(), "v") == 0) // value 101 | { 102 | int index = m->getInt(0); 103 | switch (index) 104 | { 105 | case COUNT_INT_DEFS + 0: 106 | m->returns(__TIME__); 107 | break; 108 | case COUNT_INT_DEFS + 1: 109 | m->returns(__DATE__); 110 | break; 111 | case COUNT_INT_DEFS + 2: 112 | m->returns(__VERSION__); 113 | break; 114 | case COUNT_INT_DEFS + 3: 115 | m->returns(MCU); 116 | break; 117 | 118 | default: 119 | #ifdef USE_PGM 120 | int32_t value = pgm_read_dword(&(value_table[index])); 121 | #else 122 | int32_t value = value_table[index]; 123 | #endif 124 | m->returns(value); 125 | } 126 | } 127 | 128 | } 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /Nanpy/DallasTemperatureClass.cpp: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | #if USE_DallasTemperature 4 | 5 | #include 6 | #include 7 | #include 8 | #include "DallasTemperatureClass.h" 9 | #include 10 | 11 | const char* nanpy::DallasTemperatureClass::get_firmware_id() 12 | { 13 | return "DallasTemperature"; 14 | } 15 | 16 | void nanpy::DallasTemperatureClass::elaborate( nanpy::MethodDescriptor* m ) { 17 | ObjectsManager::elaborate(m); 18 | 19 | if (strcmp(m->getName(),"new") == 0) { 20 | int prm = 0; 21 | OneWire* wr = new OneWire(m->getInt(0)); 22 | DallasTemperature* dt = new DallasTemperature(&(*wr)); 23 | v.insert(dt); 24 | dt->begin(); 25 | m->returns(v.getLastIndex()); 26 | } 27 | 28 | if (strcmp(m->getName(), "setResolution") == 0) { 29 | v[m->getObjectId()]->setResolution(m->getInt(0)); 30 | m->returns(0); 31 | } 32 | 33 | if (strcmp(m->getName(), "getResolution") == 0) { 34 | m->returns(v[m->getObjectId()]->getResolution()); 35 | } 36 | 37 | if (strcmp(m->getName(), "requestTemperatures") == 0) { 38 | if (m->getNArgs() == 1) { 39 | m->returns(v[m->getObjectId()]->requestTemperaturesByIndex(m->getInt(0))); 40 | } else if (m->getNArgs() > 1) { 41 | byte addr[8]; 42 | for(int i = 0 ; i < m->getNArgs() ; i++) { 43 | addr[i] = m->getByte(i); 44 | } 45 | m->returns(v[m->getObjectId()]->requestTemperaturesByAddress(addr)); 46 | } else { 47 | v[m->getObjectId()]->requestTemperatures(); 48 | m->returns(0); 49 | } 50 | } 51 | 52 | if (strcmp(m->getName(), "getTempC") == 0) { 53 | if(m->getNArgs() == 1) { 54 | m->returns(v[m->getObjectId()]->getTempCByIndex(m->getInt(0))); 55 | } else { 56 | byte addr[8]; 57 | for(int i = 0 ; i < m->getNArgs() ; i++) { 58 | addr[i] = m->getByte(i); 59 | } 60 | m->returns(v[m->getObjectId()]->getTempC(addr)); 61 | } 62 | } 63 | 64 | if (strcmp(m->getName(), "getTempF") == 0) { 65 | if(m->getNArgs() == 1) { 66 | m->returns(v[m->getObjectId()]->getTempFByIndex(m->getInt(0))); 67 | } else { 68 | byte addr[8]; 69 | for(int i = 0 ; i < m->getNArgs() ; i++) { 70 | addr[i] = m->getByte(i); 71 | } 72 | m->returns(v[m->getObjectId()]->getTempF(addr)); 73 | } 74 | } 75 | 76 | if (strcmp(m->getName(), "getAddress") == 0) { 77 | byte addr[8]; 78 | String addr_hex = String(); 79 | if(!v[m->getObjectId()]->getAddress(addr, m->getInt(0))) { 80 | m->returns(1); 81 | return; 82 | } 83 | 84 | char stmp[3]; 85 | for( int cc = 0; cc < 8; cc++ ) 86 | { 87 | sprintf(stmp, "%02X", addr[cc]); 88 | addr_hex.concat( stmp ); 89 | if (cc < 7) 90 | addr_hex.concat( "." ); 91 | } 92 | m->returns(addr_hex); 93 | } 94 | 95 | if (strcmp(m->getName(), "getDeviceCount") == 0) { 96 | m->returns(v[m->getObjectId()]->getDeviceCount()); 97 | } 98 | }; 99 | #endif 100 | -------------------------------------------------------------------------------- /Nanpy/MethodDescriptor.cpp: -------------------------------------------------------------------------------- 1 | #include "MethodDescriptor.h" 2 | #include 3 | #include 4 | #include "ComChannel.h" 5 | #include "consts.h" 6 | 7 | char** nanpy::MethodDescriptor::stack_pool = 0; 8 | int nanpy::MethodDescriptor::stack_pool_size = 3; 9 | 10 | nanpy::MethodDescriptor::MethodDescriptor() { 11 | 12 | char buff[MAX_READ_BUFFER_SIZE]; 13 | 14 | ComChannel::readLine(this->classname); 15 | 16 | ComChannel::readLine(buff); 17 | this->objid = atoi(buff); 18 | 19 | ComChannel::readLine(buff); 20 | this->n_args = atoi(buff); 21 | 22 | ComChannel::readLine(this->name); 23 | 24 | if (this->n_args > nanpy::MethodDescriptor::stack_pool_size) { 25 | if(nanpy::MethodDescriptor::stack_pool != 0) { 26 | for(int n = 0; n < nanpy::MethodDescriptor::stack_pool_size; n++) { 27 | delete(nanpy::MethodDescriptor::stack_pool[n]); 28 | } 29 | delete(nanpy::MethodDescriptor::stack_pool); 30 | } 31 | nanpy::MethodDescriptor::stack_pool = 0; 32 | nanpy::MethodDescriptor::stack_pool_size = this->n_args; 33 | } 34 | 35 | if (nanpy::MethodDescriptor::stack_pool == 0) { 36 | nanpy::MethodDescriptor::stack_pool = (char**)malloc(sizeof(char*) * nanpy::MethodDescriptor::stack_pool_size); 37 | for(int i = 0; i < nanpy::MethodDescriptor::stack_pool_size; i++) { 38 | nanpy::MethodDescriptor::stack_pool[i] = (char*)malloc(sizeof(char) * MAX_READ_BUFFER_SIZE); 39 | } 40 | } 41 | 42 | this->stack = nanpy::MethodDescriptor::stack_pool; 43 | 44 | for(int n = 0; n < this->n_args; n++) { 45 | ComChannel::readLine(this->stack[n]); 46 | } 47 | }; 48 | 49 | int nanpy::MethodDescriptor::getNArgs() { 50 | return this->n_args; 51 | }; 52 | 53 | bool nanpy::MethodDescriptor::getBool(int n) { 54 | return strcmp(this->stack[n], "True") == 0 ? true : false; 55 | }; 56 | 57 | int nanpy::MethodDescriptor::getInt(int n) { 58 | return atoi(this->stack[n]); 59 | }; 60 | 61 | byte nanpy::MethodDescriptor::getByte(int n) { 62 | return byte(getInt(n)); 63 | }; 64 | 65 | float nanpy::MethodDescriptor::getFloat(int n) { 66 | return atof(this->stack[n]); 67 | }; 68 | 69 | double nanpy::MethodDescriptor::getDouble(int n) { 70 | return atof(this->stack[n]); 71 | }; 72 | 73 | char* nanpy::MethodDescriptor::getString(int n) { 74 | return this->stack[n]; 75 | }; 76 | 77 | char* nanpy::MethodDescriptor::getClass() { 78 | return this->classname; 79 | }; 80 | 81 | int nanpy::MethodDescriptor::getObjectId() { 82 | return this->objid; 83 | }; 84 | 85 | char* nanpy::MethodDescriptor::getName() { 86 | return this->name; 87 | }; 88 | 89 | void nanpy::MethodDescriptor::returns(String& val) { 90 | ComChannel::println(val); 91 | } 92 | 93 | void nanpy::MethodDescriptor::returns(const char* val) { 94 | ComChannel::println(val); 95 | } 96 | 97 | void nanpy::MethodDescriptor::returns(char val) { 98 | ComChannel::println(val); 99 | } 100 | 101 | void nanpy::MethodDescriptor::returns(unsigned char val) { 102 | ComChannel::println(val); 103 | } 104 | 105 | void nanpy::MethodDescriptor::returns(int val) { 106 | ComChannel::println(val); 107 | } 108 | 109 | void nanpy::MethodDescriptor::returns(unsigned int val) { 110 | ComChannel::println(val); 111 | } 112 | 113 | void nanpy::MethodDescriptor::returns(float val) { 114 | ComChannel::println(val); 115 | } 116 | 117 | void nanpy::MethodDescriptor::returns(double val) { 118 | ComChannel::println(val); 119 | } 120 | 121 | void nanpy::MethodDescriptor::returns(long val) { 122 | ComChannel::println(val); 123 | } 124 | 125 | void nanpy::MethodDescriptor::returns(unsigned long val) { 126 | ComChannel::println(val); 127 | } 128 | 129 | -------------------------------------------------------------------------------- /Nanpy/EspClass.cpp: -------------------------------------------------------------------------------- 1 | //#include "cfg_all.h" 2 | 3 | #ifdef ESP8266 4 | 5 | #include "EspClass.h" 6 | #include 7 | 8 | const char* nanpy::EspClass::get_firmware_id() 9 | { 10 | return "Esp"; 11 | } 12 | 13 | //https://github.com/esp8266/Arduino/blob/master/cores/esp8266/Esp.cpp 14 | void nanpy::EspClass::elaborate( nanpy::MethodDescriptor* m ) { 15 | if (strcmp(m->getName(), "wdtEnable") == 0) { 16 | ESP.wdtEnable(100); 17 | m->returns(0); 18 | } 19 | if (strcmp(m->getName(), "wdtDisable") == 0) { 20 | ESP.wdtDisable(); 21 | m->returns(0); 22 | } 23 | 24 | if (strcmp(m->getName(), "wdtFeed") == 0) { 25 | ESP.wdtFeed(); 26 | m->returns(0); 27 | } 28 | // if (strcmp(m->getName(), "deepSleep") == 0) { 29 | // ESP.deepSleep(); 30 | // m->returns(0); 31 | // } 32 | if (strcmp(m->getName(), "reset") == 0) { 33 | ESP.reset(); 34 | m->returns(0); 35 | } 36 | if (strcmp(m->getName(), "restart") == 0) { 37 | ESP.restart(); 38 | m->returns(0); 39 | } 40 | if (strcmp(m->getName(), "getVcc") == 0) { 41 | m->returns(ESP.getVcc()); 42 | } 43 | if (strcmp(m->getName(), "getFreeHeap") == 0) { 44 | m->returns(ESP.getFreeHeap()); 45 | } 46 | if (strcmp(m->getName(), "getChipId") == 0) { 47 | m->returns(ESP.getChipId()); 48 | } 49 | if (strcmp(m->getName(), "getSdkVersion") == 0) { 50 | m->returns(ESP.getSdkVersion()); 51 | } 52 | if (strcmp(m->getName(), "getBootVersion") == 0) { 53 | m->returns(ESP.getBootVersion()); 54 | } 55 | if (strcmp(m->getName(), "getBootMode") == 0) { 56 | m->returns(ESP.getBootMode()); 57 | } 58 | if (strcmp(m->getName(), "getCpuFreqMHz") == 0) { 59 | m->returns(ESP.getCpuFreqMHz()); 60 | } 61 | if (strcmp(m->getName(), "getFlashChipId") == 0) { 62 | m->returns(ESP.getFlashChipId()); 63 | } 64 | if (strcmp(m->getName(), "getFlashChipRealSize") == 0) { 65 | m->returns(ESP.getFlashChipRealSize()); 66 | } 67 | 68 | if (strcmp(m->getName(), "getFlashChipSize") == 0) { 69 | m->returns(ESP.getFlashChipSize()); 70 | } 71 | if (strcmp(m->getName(), "getFlashChipSpeed") == 0) { 72 | m->returns(ESP.getFlashChipSpeed()); 73 | } 74 | if (strcmp(m->getName(), "getFlashChipMode") == 0) { 75 | m->returns(ESP.getFlashChipMode()); 76 | } 77 | // if (strcmp(m->getName(), "magicFlashChipSize") == 0) { 78 | // m->returns(ESP.magicFlashChipSize()); 79 | // } 80 | // if (strcmp(m->getName(), "magicFlashChipSpeed") == 0) { 81 | // m->returns(ESP.magicFlashChipSpeed()); 82 | // } 83 | // if (strcmp(m->getName(), "magicFlashChipMode") == 0) { 84 | // m->returns(ESP.magicFlashChipMode()); 85 | // } 86 | if (strcmp(m->getName(), "getFlashChipSizeByChipId") == 0) { 87 | m->returns(ESP.getFlashChipSizeByChipId()); 88 | } 89 | // if (strcmp(m->getName(), "checkFlashConfig") == 0) { 90 | // m->returns(ESP.checkFlashConfig()); 91 | // } 92 | if (strcmp(m->getName(), "getResetReason") == 0) { 93 | String s = ESP.getResetReason(); 94 | m->returns(s); 95 | } 96 | if (strcmp(m->getName(), "getResetInfo") == 0) { 97 | String s = ESP.getResetInfo(); 98 | m->returns(s); 99 | } 100 | if (strcmp(m->getName(), "getSketchSize") == 0) { 101 | m->returns(ESP.getSketchSize()); 102 | } 103 | if (strcmp(m->getName(), "getFreeSketchSpace") == 0) { 104 | m->returns(ESP.getFreeSketchSpace()); 105 | } 106 | if (strcmp(m->getName(), "flashEraseSector") == 0) { 107 | m->returns(ESP.flashEraseSector(m->getInt(0))); 108 | } 109 | if (strcmp(m->getName(), "flashWrite") == 0) { 110 | uint32_t data = m->getInt(1); 111 | m->returns(ESP.flashWrite(m->getInt(0), &data, 1)); 112 | } 113 | if (strcmp(m->getName(), "flashRead") == 0) { 114 | uint32_t data; 115 | ESP.flashRead(m->getInt(0), &data, 1); 116 | m->returns(data); 117 | } 118 | }; 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /Nanpy/Nanpy.ino: -------------------------------------------------------------------------------- 1 | #include "cfg_all.h" 2 | 3 | // external libraries should be put inside #if ... #endif 4 | // internal headers not. 5 | 6 | #if USE_MCP41xxx 7 | #include 8 | #endif 9 | 10 | #if USE_EEPROM 11 | #include 12 | #endif 13 | 14 | #if USE_Servo 15 | #include 16 | #endif 17 | 18 | #if USE_LiquidCrystal 19 | #include 20 | #endif 21 | 22 | #if USE_LiquidCrystal_I2C 23 | #include 24 | #endif 25 | 26 | #if USE_Stepper 27 | #include 28 | #endif 29 | 30 | #if USE_OneWire 31 | #include 32 | #endif 33 | 34 | #if USE_DallasTemperature 35 | #include 36 | #endif 37 | 38 | #if USE_CapacitiveSensor 39 | #include 40 | #endif 41 | 42 | #if USE_DHT 43 | #include 44 | #endif 45 | 46 | #if USE_Wire 47 | #include 48 | #endif 49 | 50 | #if USE_TLC5947 51 | #include 52 | #endif 53 | 54 | 55 | #include "MCP41xxxClass.h" 56 | #include "BaseClass.h" 57 | #include "ArduinoClass.h" 58 | #include "OneWireClass.h" 59 | #include "StepperClass.h" 60 | #include "ServoClass.h" 61 | #include "DallasTemperatureClass.h" 62 | #include "LiquidCrystalClass.h" 63 | #include "LiquidCrystalClass_I2C.h" 64 | #include "CapacitiveSensorClass.h" 65 | #include "ToneClass.h" 66 | #include "MethodDescriptor.h" 67 | #include "ComChannel.h" 68 | #include "EEPROMClass.h" 69 | #include "RAMClass.h" 70 | #include "DHTClass.h" 71 | 72 | #include "DefineClass.h" 73 | #include "ArduinoCoreClass.h" 74 | #include "WatchdogClass.h" 75 | #include "RegisterClass.h" 76 | #include "CounterClass.h" 77 | #include "InfoClass.h" 78 | #include "WireClass.h" 79 | 80 | #include "TLC5947Class.h" 81 | #include "EspClass.h" 82 | #include "UltrasonicClass.h" 83 | #include "ColorSensorClass.h" 84 | 85 | using namespace nanpy; 86 | 87 | MethodDescriptor *m = NULL; 88 | 89 | void setup() { 90 | disable_watchdog_at_startup(); 91 | 92 | REGISTER_CLASS(ArduinoClass); // 0.8 k 93 | // 94 | REGISTER_CLASS_CONDITIONAL(MCP41xxxClass, USE_MCP41xxx); 95 | REGISTER_CLASS_CONDITIONAL(nanpy::EEPROMClass, USE_EEPROM); // 0.3 k 96 | REGISTER_CLASS_CONDITIONAL(nanpy::RAMClass, USE_RAM); // 97 | REGISTER_CLASS_CONDITIONAL(LiquidCrystalClass, USE_LiquidCrystal); // 2.3 k 98 | REGISTER_CLASS_CONDITIONAL(LiquidCrystalClass_I2C, USE_LiquidCrystal_I2C); 99 | REGISTER_CLASS_CONDITIONAL(OneWireClass, USE_OneWire); // 1.7 k 100 | REGISTER_CLASS_CONDITIONAL(DallasTemperatureClass, USE_DallasTemperature); // 6.1 k 101 | REGISTER_CLASS_CONDITIONAL(StepperClass, USE_Stepper); // 0.8 k 102 | REGISTER_CLASS_CONDITIONAL(ServoClass, USE_Servo); // 2.5 k 103 | REGISTER_CLASS_CONDITIONAL(ToneClass, USE_Tone); // 2.2 k 104 | REGISTER_CLASS_CONDITIONAL(CapacitiveSensorClass, USE_CapacitiveSensor); // 2.2 k 105 | REGISTER_CLASS_CONDITIONAL(DefineClass, USE_Define); // 0.6 k 106 | REGISTER_CLASS_CONDITIONAL(ArduinoCoreClass, USE_ArduinoCore); // 107 | REGISTER_CLASS_CONDITIONAL(WatchdogClass, USE_Watchdog); // 0.2 k 108 | REGISTER_CLASS_CONDITIONAL(RegisterClass, USE_Register); // 1.5 k 109 | 110 | REGISTER_CLASS_CONDITIONAL(CounterClass, USE_Counter); // 111 | REGISTER_CLASS_CONDITIONAL(InfoClass, USE_Info); // 112 | REGISTER_CLASS_CONDITIONAL(DHTClass, USE_DHT); 113 | REGISTER_CLASS_CONDITIONAL(WireClass, USE_Wire); 114 | 115 | REGISTER_CLASS_CONDITIONAL(TLC5947Class, USE_TLC5947); 116 | 117 | REGISTER_CLASS_CONDITIONAL(nanpy::EspClass, USE_ESP); 118 | 119 | // GW Classes 120 | REGISTER_CLASS_CONDITIONAL(UltrasonicClass, USE_Ultrasonic); 121 | REGISTER_CLASS_CONDITIONAL(ColorSensorClass, USE_ColorSensor); 122 | 123 | ComChannel::connect(); 124 | } 125 | 126 | void loop() { 127 | if(ComChannel::available()) { 128 | m = new MethodDescriptor(); 129 | Register::elaborate(m); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /codegen/__init__.py: -------------------------------------------------------------------------------- 1 | from path import Path 2 | 3 | 4 | def read_define(fname, name): 5 | for line in Path(fname).lines(): 6 | ls = line.split(name) 7 | if len(ls) > 1: 8 | if ls[0].strip().strip('#') == 'define': 9 | return ls[1].strip() 10 | 11 | 12 | class Codegen(object): 13 | 14 | def __init__(self, root): 15 | self.root = root 16 | 17 | def header(self, avrlibc=True): 18 | s = ''' 19 | // this file was generated by codegen.py 20 | ''' 21 | if avrlibc: 22 | s += ''' 23 | // __AVR_LIBC_VERSION_STRING__ = {version} 24 | // __AVR_LIBC_DATE_STRING__ = {date} 25 | \n'''.format( 26 | version=self.version(), 27 | date=self.date(), 28 | ) 29 | 30 | return (s) 31 | 32 | def version(self): 33 | return ( 34 | read_define(self.root / 'version.h', '__AVR_LIBC_VERSION_STRING__') 35 | ) 36 | 37 | def date(self): 38 | return read_define(self.root / 'version.h', '__AVR_LIBC_DATE_STRING__') 39 | 40 | def write_header(self, hfile, text, avrlibc=True): 41 | print 'writing to %s' % hfile 42 | hfile.write_text(self.header(avrlibc) + text) 43 | 44 | def regs(self, target): 45 | print '== generating code for registers ==' 46 | valid = set() 47 | defs = set() 48 | print 'reading %s directory' % self.root 49 | for h in Path(self.root).walkfiles('*.h'): 50 | for x in h.lines(): 51 | x = x.replace('#', '').strip() 52 | ls = x.split() + [''] * 4 53 | if 'define' == ls[0]: 54 | if '_struct' not in ls[1]: 55 | if '_SFR_IO8' in ls[2] or '_SFR_MEM8' in ls[2]: 56 | valid.add(ls[1]) 57 | if '_SFR_IO16' in ls[2] or '_SFR_MEM16' in ls[2]: 58 | valid.add(ls[1]) 59 | 60 | ok = True 61 | if '(' in ls[2]: 62 | ok = False 63 | if ls[1] != ls[1].upper(): 64 | ok = False 65 | if ls[1].startswith('_'): 66 | ok = False 67 | for s in ['(', '_vect', '_H', 'eeprom']: 68 | if s in ls[1]: 69 | ok = False 70 | if ok: 71 | defs.add(ls[1]) 72 | exlude_regs = ['SPDR0'] 73 | valid = filter(lambda x: x not in exlude_regs, valid) 74 | valid = sorted(valid) 75 | TEMPLATE = ''' 76 | #ifdef {0} 77 | DEFINE({0}) 78 | #else 79 | MISSING({0}) 80 | #endif''' 81 | cpp = '\n'.join([TEMPLATE.format(x) for x in valid]) 82 | 83 | self.write_header(target, cpp) 84 | 85 | def mcu(self, target): 86 | print '== generating code for MCUs ==' 87 | valid = set() 88 | print 'reading %s directory' % self.root 89 | for h in self.root.walkfiles('*.h'): 90 | for x in h.lines(): 91 | x = x.replace('#', '').strip() 92 | x = x.replace('!', '').strip() 93 | ls = x.split() + [''] * 4 94 | if ls[0] in ['elif', 'if']: 95 | for t in ls: 96 | if 'defined' in t or 'defined' in x: 97 | if '__AVR_AT' in t: 98 | t = t.replace('defined', '') 99 | t = t.replace('(', '') 100 | t = t.replace(')', '') 101 | t = t.strip() 102 | valid.add(t) 103 | 104 | valid = sorted(valid) 105 | TEMPLATE = ''' 106 | #ifdef {0} 107 | # ifdef MCU 108 | # error "MCU is already defined" 109 | # endif 110 | # define MCU "{0}" 111 | #endif''' 112 | cpp = '\n'.join([TEMPLATE.format(x) for x in valid]) 113 | self.write_header(target, cpp) 114 | 115 | 116 | def main(): 117 | firmware_path = Path(__file__).abspath().parent.parent 118 | nanpy_path = Path(__file__).abspath().parent.parent / 'nanpy' 119 | avr_include_path = Path('/usr/lib/avr/include/avr/') 120 | 121 | x = Codegen(avr_include_path) 122 | 123 | x.regs(firmware_path / 'Nanpy' / 'generated_avr_registers.h') 124 | 125 | x.mcu(firmware_path / 'Nanpy' / 'generated_mcu.h') 126 | 127 | print 'done' 128 | 129 | if __name__ == '__main__': 130 | main() 131 | -------------------------------------------------------------------------------- /Nanpy/ComChannel.cpp: -------------------------------------------------------------------------------- 1 | #include "ComChannel.h" 2 | #include 3 | 4 | #if USE_WIFI_CONNECTION 5 | 6 | #include 7 | #include 8 | 9 | #define DNS_NAME "nanpy" 10 | #define SERVER_PORT 5678 11 | #define SerialDebug Serial 12 | #define TIMEOUT 10 13 | 14 | WiFiServer server(SERVER_PORT); 15 | WiFiClient client; 16 | 17 | void nanpy::ComChannel::connect() 18 | { 19 | SerialDebug.begin(115200); 20 | SerialDebug.println(""); 21 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 22 | SerialDebug.print("\nConnecting to "); 23 | SerialDebug.println(WIFI_SSID); 24 | uint8_t i = 0; 25 | while (WiFi.status() != WL_CONNECTED && i++ < TIMEOUT) 26 | { 27 | delay(1000); 28 | Serial.print("."); 29 | } 30 | if(i > TIMEOUT) 31 | { 32 | SerialDebug.println(""); 33 | SerialDebug.print("Could not connect to "); 34 | SerialDebug.println(WIFI_SSID); 35 | while(1) 36 | { 37 | delay(500); 38 | } 39 | } 40 | 41 | SerialDebug.println(""); 42 | 43 | if (MDNS.begin(DNS_NAME)) 44 | { 45 | SerialDebug.println("MDNS responder started"); 46 | SerialDebug.print("ping "); 47 | SerialDebug.print(DNS_NAME); 48 | SerialDebug.println(".local"); 49 | } 50 | 51 | SerialDebug.println(""); 52 | 53 | //start UART and the server 54 | server.begin(); 55 | server.setNoDelay(true); 56 | 57 | SerialDebug.print("ping "); 58 | SerialDebug.println(WiFi.localIP()); 59 | 60 | SerialDebug.print("port:"); 61 | SerialDebug.println(SERVER_PORT); 62 | } 63 | 64 | bool nanpy::ComChannel::available() 65 | { 66 | if (!client.connected()) 67 | { 68 | // try to connect to a new client 69 | client = server.available(); 70 | if (client.connected()) 71 | SerialDebug.println("client connected"); 72 | } 73 | else 74 | { 75 | // read data from the connected client 76 | return (client.available() > 0); 77 | } 78 | return false; 79 | } 80 | 81 | char nanpy::ComChannel::read_buffer[MAX_READ_BUFFER_SIZE] = {0}; 82 | 83 | void readLineFromSerial(char* extbuff) { 84 | int i=0; 85 | char ch = '0'; 86 | char* buff = nanpy::ComChannel::read_buffer; 87 | do { 88 | ch = client.read(); 89 | if(ch < 255 && ch >= 0) { 90 | buff[i++] = ch; 91 | } 92 | if (i == MAX_READ_BUFFER_SIZE - 1) { 93 | buff[i] = '\0'; 94 | break; 95 | } 96 | } while(ch != '\0'); 97 | strcpy(extbuff, buff); 98 | }; 99 | 100 | void nanpy::ComChannel::readLine(char* extbuff) { 101 | readLineFromSerial(extbuff); 102 | } 103 | 104 | void nanpy::ComChannel::println(String& val) { 105 | client.println(val); 106 | } 107 | 108 | void nanpy::ComChannel::println(const char* val) { 109 | client.println(val); 110 | } 111 | 112 | void nanpy::ComChannel::println(int val) { 113 | client.println(val); 114 | } 115 | 116 | void nanpy::ComChannel::println(unsigned int val) { 117 | client.println(val); 118 | } 119 | 120 | void nanpy::ComChannel::println(float val) { 121 | client.println(val); 122 | } 123 | 124 | void nanpy::ComChannel::println(double val) { 125 | client.println(val); 126 | } 127 | 128 | void nanpy::ComChannel::println(long val) { 129 | client.println(val); 130 | } 131 | 132 | void nanpy::ComChannel::println(unsigned long val) { 133 | client.println(val); 134 | } 135 | 136 | 137 | #else 138 | char nanpy::ComChannel::read_buffer[MAX_READ_BUFFER_SIZE] = {0}; 139 | 140 | void readLineFromSerial(char* extbuff) { 141 | int i=0; 142 | char ch = '0'; 143 | char* buff = nanpy::ComChannel::read_buffer; 144 | do { 145 | ch = COMM_SERIAL.read(); 146 | if(ch < 255 && ch >= 0) { 147 | buff[i++] = ch; 148 | } 149 | if (i == MAX_READ_BUFFER_SIZE - 1) { 150 | buff[i] = '\0'; 151 | break; 152 | } 153 | } while(ch != '\0'); 154 | strcpy(extbuff, buff); 155 | }; 156 | 157 | bool nanpy::ComChannel::available() { 158 | if (COMM_SERIAL.available() > 0) 159 | return true; 160 | else 161 | return false; 162 | } 163 | 164 | void nanpy::ComChannel::connect() { 165 | COMM_SERIAL.begin(BAUDRATE); 166 | } 167 | 168 | void nanpy::ComChannel::println(String& val) { 169 | COMM_SERIAL.println(val); 170 | } 171 | 172 | void nanpy::ComChannel::println(const char* val) { 173 | COMM_SERIAL.println(val); 174 | } 175 | 176 | void nanpy::ComChannel::println(int val) { 177 | COMM_SERIAL.println(val); 178 | } 179 | 180 | void nanpy::ComChannel::println(unsigned int val) { 181 | COMM_SERIAL.println(val); 182 | } 183 | 184 | void nanpy::ComChannel::println(float val) { 185 | COMM_SERIAL.println(val); 186 | } 187 | 188 | void nanpy::ComChannel::println(double val) { 189 | COMM_SERIAL.println(val); 190 | } 191 | 192 | void nanpy::ComChannel::println(long val) { 193 | COMM_SERIAL.println(val); 194 | } 195 | 196 | void nanpy::ComChannel::println(unsigned long val) { 197 | COMM_SERIAL.println(val); 198 | } 199 | 200 | void nanpy::ComChannel::readLine(char* extbuff) { 201 | readLineFromSerial(extbuff); 202 | } 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /Nanpy/timers.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FreqCount_timers_h_ 3 | #define FreqCount_timers_h_ 4 | 5 | #include 6 | #include 7 | 8 | // Arduino Mega 9 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 10 | // #define COUNTER_USE_TIMER1 // T1 is not connected 11 | // #define COUNTER_USE_TIMER3 // T3 is not connected 12 | // #define COUNTER_USE_TIMER4 // T4 is not connected 13 | #define COUNTER_USE_TIMER5 // T5 is pin 47 14 | #define TIMER_USE_TIMER2 15 | 16 | // Teensy 2.0 17 | #elif defined(__AVR_ATmega32U4__) 18 | #define COUNTER_USE_TIMER1 // T1 is pin 11 (has LED connected) 19 | #define TIMER_USE_TIMER4H 20 | 21 | // Teensy++ 1.0 & 2.0 22 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 23 | #define COUNTER_USE_TIMER1 // T1 is pin 6 (has LED connected) 24 | //#define COUNTER_USE_TIMER3 // T3 is pin 13 25 | #define TIMER_USE_TIMER2 26 | 27 | // Sanguino 28 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 29 | #define COUNTER_USE_TIMER1 // T1 is pin 1 30 | #define TIMER_USE_TIMER2 31 | 32 | // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc 33 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 34 | #define COUNTER_USE_TIMER1 // T1 is pin 5 35 | #define TIMER_USE_TIMER2 36 | 37 | #else 38 | #error "Unknown chip, please edit me with timer+counter definitions" 39 | 40 | #endif 41 | 42 | 43 | /**********************************************/ 44 | /* Counter Hardware Abstraction */ 45 | /**********************************************/ 46 | 47 | #if defined(COUNTER_USE_TIMER1) // 16 bit Timer 1 48 | 49 | static uint8_t saveTCCR1A, saveTCCR1B; 50 | 51 | static inline void counter_init(void) 52 | { 53 | saveTCCR1A = TCCR1A; 54 | saveTCCR1B = TCCR1B; 55 | TCCR1B = 0; 56 | TCCR1A = 0; 57 | TCNT1 = 0; 58 | TIFR1 = (1<= 16000000L 238 | #define TIMER2_OCR2A_1MS_VAL 124 // div 125 239 | #define TIMER2_TCCR2B_1MS_VAL (1<> 3; 307 | OCR2A = TIMER2_OCR2A_8MS_VAL; 308 | startTCCR2B = TIMER2_TCCR2B_8MS_VAL; 309 | } else if ((msec & 3) == 0) { 310 | gate_len = msec >> 2; 311 | OCR2A = TIMER2_OCR2A_4MS_VAL; 312 | startTCCR2B = TIMER2_TCCR2B_4MS_VAL; 313 | } else if ((msec & 1) == 0) { 314 | gate_len = msec >> 1; 315 | OCR2A = TIMER2_OCR2A_2MS_VAL; 316 | startTCCR2B = TIMER2_TCCR2B_2MS_VAL; 317 | } else { 318 | gate_len = msec; 319 | OCR2A = TIMER2_OCR2A_1MS_VAL; 320 | startTCCR2B = TIMER2_TCCR2B_1MS_VAL; 321 | } 322 | TIFR2 = (1<: 355 | 2 326: 1f 92 push r1 356 | 2 328: 0f 92 push r0 357 | 1 32a: 0f b6 in r0, 0x3f ; 63 358 | 2 32c: 0f 92 push r0 359 | 1 32e: 11 24 eor r1, r1 360 | 2 330: ef 92 push r14 361 | 2 332: ff 92 push r15 362 | 2 334: 0f 93 push r16 363 | 2 336: 1f 93 push r17 364 | 2 338: 2f 93 push r18 365 | 2 33a: 3f 93 push r19 366 | 2 33c: 4f 93 push r20 367 | 2 33e: 5f 93 push r21 368 | 2 340: 8f 93 push r24 369 | 2 342: 9f 93 push r25 370 | 2 344: af 93 push r26 371 | 2 346: bf 93 push r27 372 | */ 373 | #define TIMER_LATENCY_CYCLES 34 374 | 375 | 376 | 377 | #elif defined(TIMER_USE_TIMER4H) // 10 bit "high speed" Timer 4 378 | 379 | #define TIMER4H_OCR4C_VAL 124 // always div 125 380 | #if F_CPU == 16000000L 381 | #define TIMER4H_TCCR4B_1MS_VAL (1<> 3; 430 | startTCCR4B = TIMER4H_TCCR4B_8MS_VAL | (1<> 2; 433 | startTCCR4B = TIMER4H_TCCR4B_4MS_VAL | (1<> 1; 436 | startTCCR4B = TIMER4H_TCCR4B_2MS_VAL | (1<