diff --git a/vscode/infclock/.gitignore b/vscode/infclock/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/vscode/infclock/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/vscode/infclock/.travis.yml b/vscode/infclock/.travis.yml new file mode 100644 index 0000000..a8bbc57 --- /dev/null +++ b/vscode/infclock/.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/infclock/.vscode/extensions.json b/vscode/infclock/.vscode/extensions.json new file mode 100644 index 0000000..0f0d740 --- /dev/null +++ b/vscode/infclock/.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/vscode/infclock/include/README b/vscode/infclock/include/README new file mode 100644 index 0000000..45496b1 --- /dev/null +++ b/vscode/infclock/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/vscode/infclock/include/clockelements.hpp b/vscode/infclock/include/clockelements.hpp new file mode 100644 index 0000000..e5393da --- /dev/null +++ b/vscode/infclock/include/clockelements.hpp @@ -0,0 +1,43 @@ + +//#include +//#include "Adafruit_NeoPixel.h" +#include + +typedef struct hue_color +{ +uint8_t hue; +uint8_t sat; +uint8_t bright; +} hue_color; + +#define FASTLEDDLY 2 + +class elements +{ +private: + /* data */ + #define BRIGHTNESS 128 + #define SATURATION 255 +public: + + uint16_t element_first_pixel, element_last_pixel; + uint8_t element_number_pixels, elements_fraction; + hue_color elements_huecolor; + + bool element_outside2inside = false; + CRGB *element_pixels; + + void init(CRGB *pixels, unsigned int first_led, unsigned int number_leds, hue_color huecolor, bool outside2inside = false); + void test(uint8_t huecolor, uint8_t saturation = SATURATION, uint8_t brightness = BRIGHTNESS, bool all_at_once = false); + void test(hue_color huecolor, bool all_at_once = false); + void test( bool all_at_once = false); + void fill(uint8_t huecolor, uint8_t saturation = SATURATION, uint8_t brightness = BRIGHTNESS); + void fill(hue_color huecolor); + void fill(void); + void clean(void); + void ffill(unsigned int fraction, uint8_t huecolor, uint8_t saturation = SATURATION, uint8_t brightness = BRIGHTNESS); + void ffill(unsigned int fraction, hue_color huecolor); + void ffill(unsigned int fraction); +}; + + diff --git a/vscode/infclock/lib/README b/vscode/infclock/lib/README new file mode 100644 index 0000000..8c9c29c --- /dev/null +++ b/vscode/infclock/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 +#include + +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/vscode/infclock/platformio.ini b/vscode/infclock/platformio.ini new file mode 100644 index 0000000..f081377 --- /dev/null +++ b/vscode/infclock/platformio.ini @@ -0,0 +1,16 @@ +; 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:env1] +board = d1_mini_pro +framework = arduino +platform_packages = +platform = espressif8266 +monitor_speed = 115200 diff --git a/vscode/infclock/src/clockelements.cpp b/vscode/infclock/src/clockelements.cpp new file mode 100644 index 0000000..fe98a52 --- /dev/null +++ b/vscode/infclock/src/clockelements.cpp @@ -0,0 +1,104 @@ +#include "clockelements.hpp" + +void elements::init(CRGB *pixels, unsigned int first_led, unsigned int number_leds, hue_color huecolor, bool outside2inside) +{ + element_pixels = pixels; + element_first_pixel = first_led; + element_number_pixels = number_leds; + element_last_pixel = first_led + number_leds - 1; + element_outside2inside = outside2inside; + elements_huecolor = huecolor; + //Serial.printf("Init pixels - first:%d last:%d number:%d outsidetoinside:%d\n", element_first_pixel, element_last_pixel, element_number_pixels, element_outside2inside); +} + +void elements::clean(void) +{ + fill(0, 0, 0); +} + +void elements::test(bool all_at_once) +{ + test(elements_huecolor.hue, elements_huecolor.sat, elements_huecolor.bright, all_at_once); +} + +void elements::test(hue_color huecolor, bool all_at_once) +{ + test(huecolor.hue, huecolor.sat, huecolor.bright, all_at_once); +} + +void elements::test(uint8_t huecolor, uint8_t saturation, uint8_t brightness, bool all_at_once) +{ + unsigned int setpix = element_outside2inside == true? element_last_pixel: element_first_pixel ; + char plus_minus = element_outside2inside == true? -1:1; + for(uint8_t nrpixel = 0; nrpixel < element_number_pixels; nrpixel++) + { + element_pixels[setpix] = CHSV(huecolor,saturation, brightness); + setpix = setpix + plus_minus; + if( all_at_once == false) + { + FastLED.show(); + delay(FASTLEDDLY); + } + } + if( all_at_once == true) + { + FastLED.show(); + delay(FASTLEDDLY); + } + delay(100); + clean(); + FastLED.show(); + delay(FASTLEDDLY); +} + +void elements::fill(void) +{ + fill(elements_huecolor.hue, elements_huecolor.sat, elements_huecolor.bright); +} + +void elements::fill(hue_color huecolor) +{ + fill(huecolor.hue, huecolor.sat, huecolor.bright); +} + +void elements::fill(uint8_t huecolor, uint8_t saturation, uint8_t brightness) +{ + for(uint8_t nrpixel = element_first_pixel; nrpixel <= element_last_pixel; nrpixel++) + { + element_pixels[nrpixel] = CHSV(huecolor,saturation, brightness); + } +} + +void elements::ffill(unsigned int fraction) +{ + ffill(fraction, elements_huecolor.hue, elements_huecolor.sat, elements_huecolor.bright); +} + +void elements::ffill(unsigned int fraction, hue_color huecolor) +{ + ffill(fraction, huecolor.hue, huecolor.sat, huecolor.bright); +} + +void elements::ffill(unsigned int fraction, uint8_t huecolor, uint8_t saturation, uint8_t brightness) +{ + uint8_t fullpixels = element_number_pixels / fraction; + uint8_t partpixels = element_number_pixels % fraction; + elements_fraction = brightness / (60/element_number_pixels); + uint8_t part_brightness = elements_fraction * partpixels; + + unsigned int current_pixel = 0; + + for(uint8_t num = 0; num < fullpixels; num++) + { + current_pixel = element_outside2inside==true? element_last_pixel - num : element_first_pixel + num; + element_pixels[current_pixel] = CHSV(huecolor,saturation, brightness); + } + + if(partpixels > 0) + { + current_pixel = element_outside2inside==true? element_last_pixel - fullpixels : element_first_pixel + fullpixels; + element_pixels[current_pixel] = CHSV(huecolor,saturation, part_brightness); + } + +} + diff --git a/vscode/infclock/src/main.cpp b/vscode/infclock/src/main.cpp new file mode 100644 index 0000000..9732129 --- /dev/null +++ b/vscode/infclock/src/main.cpp @@ -0,0 +1,258 @@ +//#include + +//#include // must be included here so that Arduino library object file references work +//#include + + +#include "clockelements.hpp" + +//SoftwareWire myWire(A4, A5); +//RtcDS3231 Rtc(myWire); + +const unsigned int PIN_BUZZER = 9; +const uint8_t PIN_PIXELS = D3; //6; + +const uint16_t NUM_RING_PIXELS = 180U; +const uint8_t NUM_SECONDS = 60U; +const uint16_t NUM_RING_SEC_PIXELS = NUM_RING_PIXELS/NUM_SECONDS; +const uint8_t NUM_MINUTES = 60U; +const uint16_t NUM_RING_MIN_PIXELS = 1; +const uint16_t NUM_POINTER_PIXELS = 6U; +const uint16_t NUM_POINTERS = 12U; +const uint16_t NUM_POINTERS_PIXELS = NUM_POINTER_PIXELS * NUM_POINTERS; +const int16_t NUM_NUMBERS = 12U; +const uint16_t NUM_NUMBER_PIXELS[NUM_NUMBERS] = {2,4,4,4,4,4,4,4,4,4,4,5}; +const uint16_t NUM_NUMBERS_PIXELS = NUM_NUMBER_PIXELS[0] + NUM_NUMBER_PIXELS[1] + NUM_NUMBER_PIXELS[2] + NUM_NUMBER_PIXELS[3] + NUM_NUMBER_PIXELS[4] + NUM_NUMBER_PIXELS[5] + NUM_NUMBER_PIXELS[6] + NUM_NUMBER_PIXELS[7] + NUM_NUMBER_PIXELS[8] + NUM_NUMBER_PIXELS[9] + NUM_NUMBER_PIXELS[10] + NUM_NUMBER_PIXELS[11]; +const uint16_t NUM_ALL_PIXELS = NUM_RING_PIXELS + NUM_POINTERS_PIXELS + NUM_NUMBERS_PIXELS; + +CRGB * pixels; + +//Adafruit_NeoPixel pixels(NUM_ALL_PIXELS, PIN_PIXELS, NEO_GRB + NEO_KHZ800); + +elements number[NUM_NUMBERS]; +elements pointer[NUM_POINTERS]; +elements ringsecs[NUM_SECONDS]; +elements ringmins[NUM_MINUTES]; + +const hue_color COLOR_SECS = {HUE_GREEN,255,128}; // green +const hue_color COLOR_HOURS = {HUE_RED,255,128}; // red +const hue_color COLOR_MINS = {HUE_BLUE,255,128}; // blue +const hue_color COLOR_NUMS = {0,0,255}; // white +const hue_color color[] = {COLOR_SECS, COLOR_MINS, COLOR_HOURS, COLOR_NUMS}; +enum color_type {COL_SECOND = 0, COL_MINUTE, COL_HOUR, COL_NUM, COL_LAST}; + +const int TICK_FREQ = 40; +const int TICK_DLY = 13; +const int TOCK_FREQ = 15; +const int TOCK_DLY = 35; +bool tick_not_tock = true; + +/* +void init_rtc() +{ + Rtc.Begin(); + + RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__); + Serial.println(); + + if (!Rtc.IsDateTimeValid()) + { + if (Rtc.LastError() != 0) + { + Serial.print("RTC communications error = "); + Serial.println(Rtc.LastError()); + } + else + { + Serial.println("RTC lost confidence in the DateTime!"); + Rtc.SetDateTime(compiled); + } + } + + if (!Rtc.GetIsRunning()) + { + Serial.println("RTC was not actively running, starting now"); + Rtc.SetIsRunning(true); + } + + RtcDateTime now = Rtc.GetDateTime(); + if (now < compiled) + { + Serial.println("RTC is older than compile time! (Updating DateTime)"); + Rtc.SetDateTime(compiled); + } + else if (now > compiled) + { + Serial.println("RTC is newer than compile time. (this is expected)"); + } + else if (now == compiled) + { + Serial.println("RTC is the same as compile time! (not expected but all is fine)"); + } + + Rtc.Enable32kHzPin(false); + Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); +} +*/ + +void init_ringmins() { + // init all the seconds shown on the ring + Serial.println("Init minutes on outer ring ..."); + unsigned int current_first_led = 1; + for(uint8_t num = 0; num < NUM_MINUTES; num++) + { + ringmins[num].init(pixels, current_first_led, NUM_RING_MIN_PIXELS, color[COL_MINUTE]); + ringmins[num].clean(); + //ringmins[num].test(true); + current_first_led += NUM_RING_PIXELS/NUM_MINUTES; + } +} + +void init_ringsecs() { + // init all the seconds shown on the ring + Serial.println("Init seconds on outer ring ..."); + unsigned int current_first_led = 0; + for(uint8_t num = 0; num < NUM_SECONDS; num++) + { + ringsecs[num].init(pixels, current_first_led, NUM_RING_SEC_PIXELS, color[COL_SECOND]); + ringsecs[num].clean(); + //ringsecs[num].test(true); + current_first_led += NUM_RING_SEC_PIXELS; + } +} + +void init_numbers() { + // init all the numbers + Serial.println("Init numbers ..."); + unsigned int current_first_led = NUM_RING_PIXELS + NUM_POINTERS_PIXELS; + for(uint8_t num = 0; num < NUM_NUMBERS; num++) + { + number[num].init(pixels, current_first_led, NUM_NUMBER_PIXELS[num],color[COL_NUM]); + number[num].clean(); + number[num].test(true); + current_first_led += NUM_NUMBER_PIXELS[num]; + } +} + +void init_pointers() { + Serial.println("Init pointers ..."); + // init all the pointers - each as 6 leds, starts at 12,11,10 ... 1, each even is inversed (goes from outside into center) + unsigned int current_first_led = NUM_RING_PIXELS; + bool is_insideoutside = false; + for(int8_t num = NUM_POINTERS-1; num >= 0; num--) + { + is_insideoutside = num%2==0? false:true; + pointer[num].init(pixels, current_first_led, NUM_POINTER_PIXELS ,color[COL_MINUTE],is_insideoutside); + pointer[num].clean(); + //pointer[num].test(); + current_first_led += NUM_POINTER_PIXELS; + } +} + +/* +void tick_tock() +{ + if(tick_not_tock == true) + {tone(PIN_BUZZER, TICK_FREQ, TICK_DLY);} + else + { tone(PIN_BUZZER, TOCK_FREQ, TOCK_DLY);} + tick_not_tock = !tick_not_tock; +} +*/ + +void init_test_pixel() +{ + pixels = (CRGB*) malloc(NUM_ALL_PIXELS * sizeof(CRGB) ); + FastLED.clearData(); + FastLED.addLeds(pixels, NUM_ALL_PIXELS); // GRB ordering is typical + FastLED.clear(true); + Serial.printf("Init LED pixels %d \n",NUM_ALL_PIXELS); + /* + for(unsigned char col = COL_SECOND; col < COL_LAST; col++) + { + unsigned int pixel = 0; + for(pixel = 0; pixel < NUM_ALL_PIXELS; pixel++) + { + if(pixel > 0) + { + pixels[pixel-1] = CHSV(0,0,0); + } + pixels[pixel] = CHSV(color[col].hue, color[col].sat, color[col].bright); + FastLED.show(); + delay(FASTLEDDLY); + } + pixels[pixel] = CHSV(0,0,0); + FastLED.show(); + delay(FASTLEDDLY); + } + */ + Serial.println("Done."); +} + +void setup() { + + ESP.wdtEnable(5000); + Serial.begin(115200); + Serial.println("Lets tick ... tock ... tick ... tock ... "); + // put your setup code here, to run once: + + init_test_pixel(); + init_ringsecs(); + init_ringmins(); + init_pointers(); + init_numbers(); + //init_rtc(); + +} + +unsigned int hour = 0; +unsigned int minute = 0; +unsigned int second = 0; + +void loop() { + + /* + RtcDateTime now = Rtc.GetDateTime(); + if(now.Second() != second) + { + pixels.clear(); + + //tick_tock(); + + hour = now.Hour(); + minute = now.Minute(); + second = now.Second(); + + pointer[hour].fill(color_pointers_hour); + //pointer[hour].ffill(color_pointers_hour, minute/(60/NUM_POINTER_PIXELS)); + pixels.show(); + + Serial.print(hour); + Serial.print(":"); + Serial.print(minute); + Serial.print(":"); + Serial.println(second); + + } + */ + + + for(unsigned int second = 0; second<60; second++) + { + minute = second == 59 ? minute + 1 : minute; + hour = minute == 60 ? hour+1 : hour; + minute = minute > 59 ? 0 : minute; + hour = hour > 11 ? 0 : hour; + + FastLED.clearData(); + ringsecs[second].fill(); + ringmins[minute].fill(); + number[hour].fill(); + FastLED.show(); + delay(100); + + //Serial.printf("%02d : %02d : %02d \n" , hour, minute, second); + } + + +} \ No newline at end of file diff --git a/vscode/infclock/test/README b/vscode/infclock/test/README new file mode 100644 index 0000000..c3b0ed6 --- /dev/null +++ b/vscode/infclock/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