summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorben Egmose <torben.egmose@gmail.com>2021-02-07 22:01:09 +0100
committerTorben Egmose <torben.egmose@gmail.com>2021-02-07 22:01:09 +0100
commit9e997ae73335267e85e1bf984bcd928960557131 (patch)
treea15281c7ce8551a6a5a1bfbceec3b020e368a98c
init commitHEADmaster
-rw-r--r--.gitignore6
-rw-r--r--.travis.yml67
-rw-r--r--.vscode/extensions.json7
-rw-r--r--include/README39
-rw-r--r--lib/README46
-rw-r--r--platformio.ini15
-rw-r--r--src/main.cpp239
-rw-r--r--test/README11
8 files changed, 430 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2de98ab
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.pio
+.pioenvs
+.piolibdeps
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..7c486f1
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,67 @@
+# Continuous Integration (CI) is the practice, in software
+# engineering, of merging all developer working copies with a shared mainline
+# several times a day < https://docs.platformio.org/page/ci/index.html >
+#
+# Documentation:
+#
+# * Travis CI Embedded Builds with PlatformIO
+# < https://docs.travis-ci.com/user/integration/platformio/ >
+#
+# * PlatformIO integration with Travis CI
+# < https://docs.platformio.org/page/ci/travis.html >
+#
+# * User Guide for `platformio ci` command
+# < https://docs.platformio.org/page/userguide/cmd_ci.html >
+#
+#
+# Please choose one of the following templates (proposed below) and uncomment
+# it (remove "# " before each line) or use own configuration according to the
+# Travis CI documentation (see above).
+#
+
+
+#
+# Template #1: General project. Test it using existing `platformio.ini`.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio run
+
+
+#
+# Template #2: The project is intended to be used as a library with examples.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# env:
+# - PLATFORMIO_CI_SRC=path/to/test/file.c
+# - PLATFORMIO_CI_SRC=examples/file.ino
+# - PLATFORMIO_CI_SRC=path/to/test/directory
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..0f0d740
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "platformio.platformio-ide"
+ ]
+}
diff --git a/include/README b/include/README
new file mode 100644
index 0000000..194dcd4
--- /dev/null
+++ b/include/README
@@ -0,0 +1,39 @@
+
+This directory is intended for project header files.
+
+A header file is a file containing C declarations and macro definitions
+to be shared between several project source files. You request the use of a
+header file in your project source file (C, C++, etc) located in `src` folder
+by including it, with the C preprocessing directive `#include'.
+
+```src/main.c
+
+#include "header.h"
+
+int main (void)
+{
+ ...
+}
+```
+
+Including a header file produces the same results as copying the header file
+into each source file that needs it. Such copying would be time-consuming
+and error-prone. With a header file, the related declarations appear
+in only one place. If they need to be changed, they can be changed in one
+place, and programs that include the header file will automatically use the
+new version when next recompiled. The header file eliminates the labor of
+finding and changing all the copies as well as the risk that a failure to
+find one copy will result in inconsistencies within a program.
+
+In C, the usual convention is to give header files names that end with `.h'.
+It is most portable to use only letters, digits, dashes, and underscores in
+header file names, and at most one dot.
+
+Read more about using header files in official GCC documentation:
+
+* Include Syntax
+* Include Operation
+* Once-Only Headers
+* Computed Includes
+
+https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000..6debab1
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in a an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+| |
+| |--Bar
+| | |--docs
+| | |--examples
+| | |--src
+| | |- Bar.c
+| | |- Bar.h
+| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+| |
+| |--Foo
+| | |- Foo.c
+| | |- Foo.h
+| |
+| |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+ |- main.c
+
+and a contents of `src/main.c`:
+```
+#include <Foo.h>
+#include <Bar.h>
+
+int main (void)
+{
+ ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html
diff --git a/platformio.ini b/platformio.ini
new file mode 100644
index 0000000..03b64bb
--- /dev/null
+++ b/platformio.ini
@@ -0,0 +1,15 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:pro8MHzatmega168]
+platform = atmelavr
+board = pro8MHzatmega168
+framework = arduino
+upload_port = /dev/ttyUSB3 \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..8a058c9
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,239 @@
+#include <Arduino.h>
+#include <Wire.h>
+const uint8_t SlaveDeviceId = 0x02;
+
+uint16_t receivedPacket[10];
+
+byte bytesSent = 0;
+byte buffer[2];
+
+uint16_t returninfo;
+
+int watchDog = 0;
+bool fallback = false;
+unsigned long tick = 0;
+int pins[18] = {0, 0, 0, 1, 0, 2, 3, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0}; // map to array
+int pin_map[7] = {0, 3, 5, 6, 9, 10, 11};
+int target[7] = {0, 0, 0, 0, 0, 0, 0};
+int current[7] = {0, 0, 0, 0, 0, 0, 0};
+int i;
+
+/**
+ * Divides a given PWM pin frequency by a divisor.
+ *
+ * The resulting frequency is equal to the base frequency divided by
+ * the given divisor:
+ * - Base frequencies:
+ * o The base frequency for pins 3, 9, 10, and 11 is 31250 Hz.
+ * o The base frequency for pins 5 and 6 is 62500 Hz.
+ * - Divisors:
+ * o The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64,
+ * 256, and 1024.
+ * o The divisors available on pins 3 and 11 are: 1, 8, 32, 64,
+ * 128, 256, and 1024.
+ *
+ * PWM frequencies are tied together in pairs of pins. If one in a
+ * pair is changed, the other is also changed to match:
+ * - Pins 5 and 6 are paired on timer0
+ * - Pins 9 and 10 are paired on timer1
+ * - Pins 3 and 11 are paired on timer2
+ *
+ * Note that this function will have side effects on anything else
+ * that uses timers:
+ * - Changes on pins 3, 5, 6, or 11 may cause the delay() and
+ * millis() functions to stop working. Other timing-related
+ * functions may also be affected.
+ * - Changes on pins 9 or 10 will cause the Servo library to function
+ * incorrectly.
+ *
+ * Thanks to macegr of the Arduino forums for his documentation of the
+ * PWM frequency divisors. His post can be viewed at:
+ * https://forum.arduino.cc/index.php?topic=16612#msg121031
+ */
+void setPwmFrequency(int pin, int divisor) {
+ byte mode;
+ if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
+ switch(divisor) {
+ case 1: mode = 0x01; break;
+ case 8: mode = 0x02; break;
+ case 64: mode = 0x03; break;
+ case 256: mode = 0x04; break;
+ case 1024: mode = 0x05; break;
+ default: return;
+ }
+ if(pin == 5 || pin == 6) {
+ TCCR0B = ((TCCR0B & 0b11111000) | mode);
+ } else {
+ TCCR1B = ((TCCR1B & 0b11111000) | mode);
+ }
+ } else if(pin == 3 || pin == 11) {
+ switch(divisor) {
+ case 1: mode = 0x01; break;
+ case 8: mode = 0x02; break;
+ case 32: mode = 0x03; break;
+ case 64: mode = 0x04; break;
+ case 128: mode = 0x05; break;
+ case 256: mode = 0x06; break;
+ case 1024: mode = 0x07; break;
+ default: return;
+ }
+ TCCR2B = ((TCCR2B & 0b11111000) | mode);
+ }
+}
+
+void receiveDataPacket(int howMany){
+ if(fallback == true || watchDog == 0)
+ {
+ fallback = false;
+ digitalWrite(LED_BUILTIN, LOW);
+ }
+ watchDog = 10;
+
+ // get bytes from i2c
+ bytesSent = 0; // clear byte counter
+ for(byte i=0; i < howMany; i++){
+ receivedPacket[i] = Wire.read();
+ }
+
+}
+
+void slavesRespond(){
+ if(bytesSent == 0){
+ switch(receivedPacket[0]){
+ case 1: // digitalWrite
+ /*
+ receivedPacket[1] = pin
+ receivedPacket[2] = value
+ */
+ pinMode(receivedPacket[1], OUTPUT); // set pin mode
+ digitalWrite(receivedPacket[1], receivedPacket[2]);
+ returninfo = 1;
+ break;
+ case 2: // digitalRead
+ /*
+ receivedPacket[1] = pin
+ */
+ pinMode(receivedPacket[1], INPUT); // set pin mode
+ returninfo = digitalRead(receivedPacket[1]);
+ break;
+ case 3: // digitalRead pullup
+ /*
+ receivedPacket[1] = pin
+ */
+ pinMode(receivedPacket[1], INPUT_PULLUP); // set pin mode
+ returninfo = digitalRead(receivedPacket[1]);
+ break;
+ case 4: // analogWrite
+ /*
+ receivedPacket[1] = pin
+ receivedPacket[2] = value
+ */
+ pinMode(receivedPacket[1], OUTPUT); // set pin mode
+ analogWrite(receivedPacket[1], receivedPacket[2]);
+ returninfo = 1;
+ break;
+ case 5: // analogRead
+ /*
+ receivedPacket[1] = pin
+ */
+ returninfo = analogRead(receivedPacket[1]);
+ break;
+ case 10: // analogWriteSlow
+ /*
+ receivedPacket[1] = pin
+ receivedPacket[2] = value
+ */
+ if(pins[receivedPacket[1]] > 0) {
+ pinMode(pins[receivedPacket[1]], OUTPUT); // set pin mode
+ target[pins[receivedPacket[1]]] = receivedPacket[2];
+ returninfo = 1;
+ } else {
+ returninfo = 0;
+ }
+ break;
+ }
+ }
+ if(bytesSent == 0){ //send first byte
+ buffer[0] = returninfo >> 8;
+ buffer[1] = returninfo & 0xff;
+ Wire.write(buffer[0]);
+ bytesSent++;
+ } else if(bytesSent == 1){ // send second byte
+ Wire.write(buffer[1]);
+ bytesSent = 0; // clear byte counter
+ }
+}
+
+void setup() {
+ setPwmFrequency(3, 8);
+ setPwmFrequency(5, 8);
+ setPwmFrequency(6, 8);
+ setPwmFrequency(9, 8);
+ setPwmFrequency(10, 8);
+ setPwmFrequency(11, 8);
+
+ pinMode(3, OUTPUT);
+ pinMode(5, OUTPUT);
+ pinMode(6, OUTPUT);
+ pinMode(9, OUTPUT);
+ pinMode(10, OUTPUT);
+ pinMode(11, OUTPUT);
+
+ analogWrite(3, 0);
+ analogWrite(5, 0);
+ analogWrite(6, 0);
+ analogWrite(9, 0);
+ analogWrite(10, 0);
+ analogWrite(11, 0);
+
+ Wire.begin(SlaveDeviceId); // join i2c bus with Slave ID
+ Wire.onReceive(receiveDataPacket); // register talk event
+ Wire.onRequest(slavesRespond); // register callback event
+
+ pinMode(LED_BUILTIN, OUTPUT);
+ digitalWrite(LED_BUILTIN, HIGH);
+}
+
+void adjust_pwm(int &l, int p, int m) {
+ if (l < m) {
+ if (l >= m - 5) {
+ l = m;
+ } else {
+ l += 5;
+ }
+ analogWrite(p, l);
+ }
+
+ if (l > m) {
+ if (l <= 5) {
+ l = 0;
+ } else {
+ l -= 5;
+ }
+ analogWrite(p, l);
+ }
+}
+
+void loop() {
+ for(i=1; i<8; i++) {
+ if(target[i]!=current[i] || fallback && 255!=current[i]) {
+ adjust_pwm(current[i],pin_map[i],fallback ? 255 : target[i]);
+ }
+ }
+
+ if(millis() - tick >= 5000) {
+ tick = millis();
+ if(watchDog > 0)
+ {
+ watchDog--;
+ }
+ else
+ {
+ fallback = true;
+ digitalWrite(LED_BUILTIN, HIGH);
+ }
+ }
+
+ delay(10);
+}
+
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..df5066e
--- /dev/null
+++ b/test/README
@@ -0,0 +1,11 @@
+
+This directory is intended for PIO Unit Testing and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PIO Unit Testing:
+- https://docs.platformio.org/page/plus/unit-testing.html