You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
731 lines
24 KiB
731 lines
24 KiB
/* |
|
|
|
TrackControl.ino |
|
|
|
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/) |
|
|
|
Copyright (c) 2018, olikraus@gmail.com |
|
All rights reserved. |
|
|
|
Redistribution and use in source and binary forms, with or without modification, |
|
are permitted provided that the following conditions are met: |
|
|
|
* Redistributions of source code must retain the above copyright notice, this list |
|
of conditions and the following disclaimer. |
|
|
|
* Redistributions in binary form must reproduce the above copyright notice, this |
|
list of conditions and the following disclaimer in the documentation and/or other |
|
materials provided with the distribution. |
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
|
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|
|
*/ |
|
|
|
#include <Arduino.h> |
|
#include <U8g2lib.h> |
|
#include <string.h> |
|
#include <stdarg.h> |
|
|
|
#ifdef U8X8_HAVE_HW_SPI |
|
#include <SPI.h> |
|
#endif |
|
#ifdef U8X8_HAVE_HW_I2C |
|
#include <Wire.h> |
|
#endif |
|
|
|
#define MENU_FONT u8g2_font_helvB18_tr |
|
#define SUBMENU_FONT u8g2_font_helvB12_tr |
|
|
|
|
|
/* |
|
158*128 |
|
bold: 65..70 |
|
normal: 71...76 |
|
*/ |
|
/* |
|
const uint8_t track_font[1646] U8G2_FONT_SECTION("track_font") = |
|
"\14\0\7\4\7\7\10\6\11\232|\2\2~\0~\0\0\0\0\0\6UA\273z\276\240\350\271\365\0" |
|
"?\200\260=\300\17\200d\17\360\3\260\327\3\374\265\36\340\17 V\17\360\7 \251\7\70\36\304{\200" |
|
"\220nk\326^n\355\255t\250\225z\207\225\200\204\225\204\203\205\342G~\315\315\374\310\257\271\231\237\271" |
|
"\231\237\271E\67sC\267\346\206n\350\205n\321K\275\320\355\377\377\377\377W\257\325\15\335V\257\352\206" |
|
"n\325K\335\320M\335\320\255\272\241\233\272\241\37\272\241\337\346\210<\30H\134\30'|\30\307\233\32h" |
|
"\233\36(\233\42\310\232(I\252,\213\311\62\13\311\70\357\367>\17\320B\17\360@\17\360O\364\0\177" |
|
"\200Vz\200?\200B=\300\37\340\264\36\340\7X\17\0Bc<%\243\352Y\60p\4Wlv\66" |
|
"DS\62M\226fy\63D\303\277\332}\65T\273\331N\355\330N\355\330N\355\330N\355\330N\15\253" |
|
"\35\333\251\241\332\261\235\32VK\264\34M\315\226\214\305Z\314\275\36@\260\36\300\201\36\340\201\36\240\211" |
|
"\36`\221\36 \231\36\340\244\36\0\235\36\300\254\36@\270\234L\1Cu\256\275\373\350\31\320B\17\20" |
|
"<\17@\66\17p\60\17\200.\17\240BO\324H\253\244L\351\204\357tP\27\312\244\14\312\244\14\352" |
|
"\240L\312\240L\252\244\14\312\244\14\312J\31\224\275T]\312\240\354\377\377\377\377\177'\203\262N\6e" |
|
"\235\316\311\240\314\311\240\314\311\240\314\311\234\316\311\234\216\351\62\241\22\36)\33)\321\2\61P\353<\316" |
|
"\3\210\216\3\61Q*\31\21\0D\236~\362\243\354\271\364\0\37\240\375\36\340\7\70\267\7\370\1\332\354" |
|
"\1\376\0\342\365\0\177\200\302z\270\206j?Fj\303%ZH\365a\313\324Y\316\264QR\224IU" |
|
"tIWTIY\64A\335\23A\336\23\71\340\363\70\342\323\70\344\263@e\263\70\346\223\70h\203\70" |
|
"js\70jc\70lS\60mC\70\355\63\60o\63\60o#\60\360\23\60q\23(r\63\20\363\203" |
|
"\267\377\377\377\377\341K\276\340\355\341\13\336\302\27\274\205/x\353n\360\346n\360\346~\354\347n\356\307" |
|
"~w?w\223'\16\0E|\63s\262\352\331\42b\304eZg\225o\205X\370X\247uX\210u" |
|
"Z\247eZW\313\264N\313\264N\313\270L\313\270L\313\264N\313j\235\226\345*.\323\262\134\225\313" |
|
"\264\354\377Z\305U\327\62\255\342\252Z\246U\134\245U\134\245eZ\245eZ\245eZ\245eX\246e" |
|
"X\26\353\254\356VH\205RH\205R\351\264L\313\304H\16\364\0B\363\0\247\363\0\345\363\0B\364" |
|
"H\13\5\0F\254\332.%\354y\344\216\17\220~\17\360\0\1\367\0\17`h\17\360\0\353\365\0!" |
|
"\361\0e\325(\17\20N\214\303JJ\264D\311\244>I\245\70\251\225\64\10\226\60H\226,\250\206(" |
|
"\350\206$(\207\42g\207\36\247\207\32\347\207\26'x\26fx\22\207x\20\246x\16\346x\14%i" |
|
"\12&y\10ei\10ey\6\244i\6\244i\10\342i\250V\325P\255jU\65T{\325\372\243Z" |
|
"\324R\255\250\26\265P-j\241\32j\241ZS\63=Skz\244gj\246Gz\213\342\240\351\251\234" |
|
"\253\271\230M\351\220\17\20\224\216\311\234)jF\0G\240\367<\341\350\271\364\0?\0z=\300\17\300" |
|
"Z\17\360\3\70\325\3\31\340B\25\37j\37\67r\237\267\5\67\276\322*\301\262*C\301*\361JN" |
|
"\67\37s\42'\363\61'r\62'r\62\37\364\61'\363A\37s\62\37sj>\350\363\377\377\377\377" |
|
"\177\365A\237G'\364\211N\346\204>\350\204>\350dN\350dN\350\324\234\320if\301 d\302 " |
|
"\341\342 \337\2!\134#!\332R)Vs\61S\243\61\316\323A\310\4R\301\65z\0\363z\200A" |
|
"z\200?\0:=\300\37\240\264\36\340\7 \23\0H[:d\343\352\71 p\343\66l\364\2C\206" |
|
"dgv\67\63\64\213Vj\365l\64[\251\325l\245V\331\210\255\330([\261\21[\261\21[e#" |
|
"\67b+\66r#\266z\65\253vjV\355\320\320L\311\26\314\265\36\340\230\36@\215\36\0\225\36\300" |
|
"\240\36 \264\36 \270\236\213\311\20I_+\374;\351\31\340:\17 \64\17PF\212\204J\250tN" |
|
"\346T;\21\24\35j\240(\324@\21\324@\21\324@\21\324@\21\324\204\42\250\11EN\4\65\377\377" |
|
"\377\377\377\377w\242N\343D\235\306\211\234\306\211\62\221\23\61\221\23\61Q\246b\242\257T\221\254\221\21" |
|
"\241\20\372\250\316\2%Q\11\1J\227{\61\344\354\71\364\0?\200\320=\300\17\200h\17\360\3\260\230" |
|
"\322\241\26\12\236\24*\36\323A\236\321a\236\317\201\232\216\241\226\215\261\226L\311\226K\331\22K\351\22" |
|
"J\371\22I\11\23H\31\23G)\223\6\61\23\6A\23\5Q\217DQ\23\4a\23\3i\23\3q" |
|
"\23\2y\23\302\210\217\1\211\23\301\220\223\0\231\217\300\240\37:\11\4\373\300\317\377\377\377\377\357N\335" |
|
"\7~\272\223\373\300\217;\271\17\374\270\17\374\270\223\373\270\23;\271\217;\261\223\373\270\23;\355>\32" |
|
"\0Ki\61r\362\352\331\42\134\244UXV\253~-\342\42\255\252E\134\244UZ\304EZ\304E\134" |
|
"\303E\134\303E\134\303E\134\303E\134\303EZ\304\65\134\244E\134\223\213\270\346\377\377\271\204k\326\32" |
|
"\256\251\65\134Sk\270Fk\270Fk\264Hkj\221\326\324\42,z\253JUT&eR\347\204L" |
|
"\211\264<\17\20@n\244N\0L\240Y.%\354\271\264\220\17p\200\17\340r\212\321f\310\242^\247" |
|
"\203XFtP\346dJeUD\305e>%V:\204V\66\304V\62\4W.dG*\244G&" |
|
"\344G\42$H cH\34\204H\30\244X\24\344H\24#I\20$I\16dI\14dY\10\244I" |
|
"\10\304\71\10\343I\6\42:\254\244J\254\223\225T\211uf%Ub\235\377\253\16\353\254J\252\303:" |
|
"U\207uTIuXGuTIuT\11\225TG\225Pi\324\62\255\223\32i\221\232\250\201\242'" |
|
"j*\246r\242h\251\6\23\0\0\0\0"; |
|
*/ |
|
|
|
/* |
|
Fontname: track |
|
Copyright: unknown |
|
Glyphs: 12/12 |
|
BBX Build Mode: 0 |
|
*/ |
|
const uint8_t track_font[1650] U8G2_FONT_SECTION("track_font") = |
|
"\14\0\7\4\7\7\10\6\11\232|\2\2~\0~\0\0\0\0\0\6UA\273z\276\240\350\271\365\0" |
|
"\77\200\260=\300\17\200d\17\360\3\260\327\3\374\265\36\340\17 V\17\360\7 \251\7\70\36\304{\200" |
|
"\220nk\326^n\355\255t\250\225z\207\225\200\204\225\204\203\205\342G~\315\315\374\310\257\271\231\237\271" |
|
"\231\237\271E\67sC\267\346\206n\350\205n\321K\275\320\355\377\377\377\377W\257\325\15\335V\257\352\206" |
|
"n\325K\335\320M\335\320\255\272\241\233\272\241\37\272\241\337\346\210<\30H\134\30'|\30\307\233\32h" |
|
"\233\36(\233\42\310\232(I\252,\213\311\62\13\311\70\357\367>\17\320B\17\360@\17\360O\364\0\177" |
|
"\200Vz\200\77\200B=\300\37\340\264\36\340\7X\17\0Bc<%\243\352Y\60p\4Wlv\66" |
|
"DS\62M\226fy\63D\303\277\332}\65T\273\331N\355\330N\355\330N\355\330N\355\330N\15\253" |
|
"\35\333\251\241\332\261\235\32VK\264\34M\315\226\214\305Z\314\275\36@\260\36\300\201\36\340\201\36\240\211" |
|
"\36`\221\36 \231\36\340\244\36\0\235\36\300\254\36@\270\234L\1Cu\256\275\373\350\31\320B\17\20" |
|
"<\17@\66\17p\60\17\200.\17\240BO\324H\253\244L\351\204\357tP\27\312\244\14\312\244\14\352" |
|
"\240L\312\240L\252\244\14\312\244\14\312J\31\224\275T]\312\240\354\377\377\377\377\177'\203\262N\6e" |
|
"\235\316\311\240\314\311\240\314\311\240\314\311\234\316\311\234\216\351\62\241\22\36)\33)\321\2\61P\353<\316" |
|
"\3\210\216\3\61Q*\31\21\0D\236~\362\243\354\271\364\0\37\240\375\36\340\7\70\267\7\370\1\332\354" |
|
"\1\376\0\342\365\0\177\200\302z\270\206j\77Fj\303%ZH\365a\313\324Y\316\264QR\224IU" |
|
"tIWTIY\64A\335\23A\336\23\71\340\363\70\342\323\70\344\263@e\263\70\346\223\70h\203\70" |
|
"js\70jc\70lS\60mC\70\355\63\60o\63\60o#\60\360\23\60q\23(r\63\20\363\203" |
|
"\267\377\377\377\377\341K\276\340\355\341\13\336\302\27\274\205/x\353n\360\346n\360\346~\354\347n\356\307" |
|
"~w\77w\223'\16\0E|\63s\262\352\331\42b\304eZg\225o\205X\370X\247uX\210u" |
|
"Z\247eZW\313\264N\313\264N\313\270L\313\270L\313\264N\313j\235\226\345*.\323\262\134\225\313" |
|
"\264\354\377Z\305U\327\62\255\342\252Z\246U\134\245U\134\245eZ\245eZ\245eZ\245eX\246e" |
|
"X\26\353\254\356VH\205RH\205R\351\264L\313\304H\16\364\0B\363\0\247\363\0\345\363\0B\364" |
|
"H\13\5\0F\254\332.%\354y\344\216\17\220~\17\360\0\1\367\0\17`h\17\360\0\353\365\0!" |
|
"\361\0e\325(\17\20N\214\303JJ\264D\311\244>I\245\70\251\225\64\10\226\60H\226,\250\206(" |
|
"\350\206$(\207\42g\207\36\247\207\32\347\207\26'x\26fx\22\207x\20\246x\16\346x\14%i" |
|
"\12&y\10ei\10ey\6\244i\6\244i\10\342i\250V\325P\255jU\65T{\325\372\243Z" |
|
"\324R\255\250\26\265P-j\241\32j\241ZS\63=Skz\244gj\246Gz\213\342\240\351\251\234" |
|
"\253\271\230M\351\220\17\20\224\216\311\234)jF\0G\240\367<\341\350\271\364\0\77\0z=\300\17\300" |
|
"Z\17\360\3\70\325\3\31\340B\25\37j\37\67r\237\267\5\67\276\322*\301\262*C\301*\361JN" |
|
"\67\37s\42'\363\61'r\62'r\62\37\364\61'\363A\37s\62\37sj>\350\363\377\377\377\377" |
|
"\177\365A\237G'\364\211N\346\204>\350\204>\350dN\350dN\350\324\234\320if\301 d\302 " |
|
"\341\342 \337\2!\134#!\332R)Vs\61S\243\61\316\323A\310\4R\301\65z\0\363z\200A" |
|
"z\200\77\0:=\300\37\240\264\36\340\7 \23\0H[:d\343\352\71 p\343\66l\364\2C\206" |
|
"dgv\67\63\64\213Vj\365l\64[\251\325l\245V\331\210\255\330([\261\21[\261\21[e#" |
|
"\67b+\66r#\266z\65\253vjV\355\320\320L\311\26\314\265\36\340\230\36@\215\36\0\225\36\300" |
|
"\240\36 \264\36 \270\236\213\311\20I_+\374;\351\31\340:\17 \64\17PF\212\204J\250tN" |
|
"\346T;\21\24\35j\240(\324@\21\324@\21\324@\21\324@\21\324\204\42\250\11EN\4\65\377\377" |
|
"\377\377\377\377w\242N\343D\235\306\211\234\306\211\62\221\23\61\221\23\61Q\246b\242\257T\221\254\221\21" |
|
"\241\20\372\250\316\2%Q\11\1J\227{\61\344\354\71\364\0\77\200\320=\300\17\200h\17\360\3\260\230" |
|
"\322\241\26\12\236\24*\36\323A\236\321a\236\317\201\232\216\241\226\215\261\226L\311\226K\331\22K\351\22" |
|
"J\371\22I\11\23H\31\23G)\223\6\61\23\6A\23\5Q\217DQ\23\4a\23\3i\23\3q" |
|
"\23\2y\23\302\210\217\1\211\23\301\220\223\0\231\217\300\240\37:\11\4\373\300\317\377\377\377\377\357N\335" |
|
"\7~\272\223\373\300\217;\271\17\374\270\17\374\270\223\373\270\23;\271\217;\261\223\373\270\23;\355>\32" |
|
"\0Ki\61r\362\352\331\42\134\244UXV\253~-\342\42\255\252E\134\244UZ\304EZ\304E\134" |
|
"\303E\134\303E\134\303E\134\303E\134\303EZ\304\65\134\244E\134\223\213\270\346\377\377\271\204k\326\32" |
|
"\256\251\65\134Sk\270Fk\270Fk\264Hkj\221\326\324\42,z\253JUT&eR\347\204L" |
|
"\211\264<\17\20@n\244N\0L\240Y.%\354\271\264\220\17p\200\17\340r\212\321f\310\242^\247" |
|
"\203XFtP\346dJeUD\305e>%V:\204V\66\304V\62\4W.dG*\244G&" |
|
"\344G\42$H cH\34\204H\30\244X\24\344H\24#I\20$I\16dI\14dY\10\244I" |
|
"\10\304\71\10\343I\6\42:\254\244J\254\223\225T\211uf%Ub\235\377\253\16\353\254J\252\303:" |
|
"U\207uTIuXGuTIuT\11\225TG\225Pi\324\62\255\223\32i\221\232\250\201\242'" |
|
"j*\246r\242h\251\6\23\0\0\0\0\4\377\377\0"; |
|
|
|
/*================================================================================*/ |
|
|
|
U8G2_ST75256_JLX256128_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 7, /* dc=*/ 6, /* reset=*/ 5); // MKR Zero, Enable U8g2 16 bit mode for this display |
|
|
|
|
|
|
|
/*================================================================================*/ |
|
|
|
uint8_t test_i2c_address(uint8_t adr) |
|
{ |
|
Wire.beginTransmission(adr); |
|
return Wire.endTransmission(false); |
|
} |
|
|
|
void system_test(void) |
|
{ |
|
u8x8_SetFont(u8g2.getU8x8(), u8x8_font_amstrad_cpc_extended_r); |
|
u8x8_Draw1x2String(u8g2.getU8x8(), 0, 0, "Oli's Spur N Controller (2018)"); |
|
u8x8_DrawString(u8g2.getU8x8(), 0, 3, "Teste I2C Weichen..."); |
|
if ( test_i2c_address(17) == 0 ) |
|
u8x8_DrawString(u8g2.getU8x8(), 26, 3, "Ok"); |
|
else |
|
u8x8_DrawString(u8g2.getU8x8(), 26, 3, "Fehler"); |
|
|
|
u8x8_DrawString(u8g2.getU8x8(), 0, 4, "Teste I2C Motortreiber..."); |
|
if ( test_i2c_address(40) == 0 ) |
|
u8x8_DrawString(u8g2.getU8x8(), 26, 4, "Ok"); |
|
else |
|
u8x8_DrawString(u8g2.getU8x8(), 26, 4, "Fehler"); |
|
|
|
/* wait for keypress */ |
|
while( u8g2.getMenuEvent() == 0 ) |
|
; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void setup(void) { |
|
|
|
// MKR Zero Test Board |
|
u8g2.begin(/*Select=*/ 0, /*Right/Next=*/ 1, /*Left/Prev=*/ 2, /*Up=*/ 4, /*Down=*/ 3, /*Home/Cancel=*/ A6); |
|
|
|
u8g2.setFontMode(1); |
|
|
|
Wire.begin(); |
|
|
|
system_test(); |
|
} |
|
|
|
/*================================================================================*/ |
|
|
|
#define LOG_BUF_LINES 7 |
|
#define LOG_BUF_LINE_LEN 32 |
|
#define LOG_FONT u8g2_font_lucasfont_alternate_tr |
|
#define LOG_FONT_LH 9 |
|
|
|
char log_buf[LOG_BUF_LINES][LOG_BUF_LINE_LEN]; |
|
uint8_t log_end = 0; |
|
|
|
//u8g2_font_u8glib_4_tr |
|
|
|
void draw_log(void) |
|
{ |
|
uint8_t i; |
|
u8g2.setFont(LOG_FONT); |
|
|
|
for( i = 0; i < LOG_BUF_LINES; i++ ) |
|
{ |
|
u8g2.drawStr(160, 64+i*LOG_FONT_LH, log_buf[i]); |
|
} |
|
} |
|
|
|
void scroll_log(void) |
|
{ |
|
uint8_t i; |
|
for( i = 1; i < LOG_BUF_LINES; i++ ) |
|
{ |
|
strcpy(log_buf[i-1], log_buf[i]); |
|
} |
|
log_buf[LOG_BUF_LINES-1][0] = '\0'; |
|
} |
|
|
|
void log_line(const char *fmt, ...) |
|
{ |
|
va_list va; |
|
|
|
va_start(va, fmt); |
|
vsnprintf(log_buf[log_end], LOG_BUF_LINE_LEN, fmt, va); |
|
log_buf[log_end][LOG_BUF_LINE_LEN-1] = '\0'; |
|
va_end(va); |
|
|
|
if ( log_end < LOG_BUF_LINES-1 ) |
|
{ |
|
log_end++; |
|
} |
|
else |
|
{ |
|
scroll_log(); |
|
|
|
} |
|
} |
|
|
|
|
|
|
|
|
|
/*================================================================================*/ |
|
|
|
struct menu_entry_type |
|
{ |
|
const uint8_t *font; |
|
uint16_t icon; |
|
const char *name; |
|
}; |
|
|
|
struct menu_state |
|
{ |
|
int16_t menu_start; /* in pixel */ |
|
int16_t frame_position; /* in pixel */ |
|
uint8_t position; /* position, array index */ |
|
}; |
|
|
|
/* |
|
Icon configuration |
|
Width and height must match the icon font size |
|
GAP: Space between the icons |
|
BGAP: Gap between the display border and the cursor. |
|
*/ |
|
#define ICON_WIDTH 64 |
|
#define ICON_HEIGHT 64 |
|
#define ICON_GAP 8 |
|
#define ICON_BGAP 16 |
|
#define ICON_Y 64+ ICON_GAP |
|
|
|
struct menu_entry_type menu_entry_list[] = |
|
{ |
|
{ u8g2_font_open_iconic_other_8x_t, 66, "Weichen-Test"}, |
|
{ u8g2_font_open_iconic_embedded_8x_t, 67, "Motor Test"}, |
|
{ u8g2_font_open_iconic_embedded_8x_t, 66, "Gear Game"}, |
|
{ u8g2_font_open_iconic_embedded_8x_t, 68, "Home"}, |
|
{ u8g2_font_open_iconic_embedded_8x_t, 72, "Configuration"}, |
|
{ NULL, 0, NULL } |
|
}; |
|
|
|
int8_t button_event = 0; // set this to 0, once the event has been processed |
|
|
|
void check_button_event(void) |
|
{ |
|
if ( button_event == 0 ) |
|
button_event = u8g2.getMenuEvent(); |
|
} |
|
|
|
|
|
void main_menu_draw(struct menu_state *state) |
|
{ |
|
int16_t x; |
|
uint8_t i; |
|
x = state->menu_start; |
|
i = 0; |
|
while( menu_entry_list[i].icon > 0 ) |
|
{ |
|
if ( x >= -ICON_WIDTH && x < u8g2.getDisplayWidth() ) |
|
{ |
|
u8g2.setFont(menu_entry_list[i].font); |
|
u8g2.drawGlyph(x, ICON_Y, menu_entry_list[i].icon ); |
|
} |
|
i++; |
|
x += ICON_WIDTH + ICON_GAP; |
|
check_button_event(); |
|
} |
|
//u8g2.drawFrame(state->frame_position-1, ICON_Y-ICON_HEIGHT-1, ICON_WIDTH+2, ICON_WIDTH+2); |
|
u8g2.drawFrame(state->frame_position-2, ICON_Y-ICON_HEIGHT-2, ICON_WIDTH+4, ICON_WIDTH+4); |
|
u8g2.drawFrame(state->frame_position-3, ICON_Y-ICON_HEIGHT-3, ICON_WIDTH+6, ICON_WIDTH+6); |
|
u8g2.drawFrame(state->frame_position-4, ICON_Y-ICON_HEIGHT-4, ICON_WIDTH+8, ICON_WIDTH+8); |
|
u8g2.drawFrame(state->frame_position-5, ICON_Y-ICON_HEIGHT-5, ICON_WIDTH+10, ICON_WIDTH+10); |
|
u8g2.drawFrame(state->frame_position-6, ICON_Y-ICON_HEIGHT-6, ICON_WIDTH+12, ICON_WIDTH+12); |
|
check_button_event(); |
|
} |
|
|
|
|
|
void main_menu_to_right(struct menu_state *state) |
|
{ |
|
if ( menu_entry_list[state->position+1].font != NULL ) |
|
{ |
|
if ( (int16_t)state->frame_position+ 2*(int16_t)ICON_WIDTH + (int16_t)ICON_BGAP < (int16_t)u8g2.getDisplayWidth() ) |
|
{ |
|
state->position++; |
|
state->frame_position += ICON_WIDTH + (int16_t)ICON_GAP; |
|
} |
|
else |
|
{ |
|
state->position++; |
|
state->frame_position = (int16_t)u8g2.getDisplayWidth() - (int16_t)ICON_WIDTH - (int16_t)ICON_BGAP; |
|
state->menu_start = state->frame_position - state->position*((int16_t)ICON_WIDTH + (int16_t)ICON_GAP); |
|
} |
|
} |
|
} |
|
|
|
void main_menu_to_left(struct menu_state *state) |
|
{ |
|
if ( state->position > 0 ) |
|
{ |
|
if ( (int16_t)state->frame_position >= (int16_t)ICON_BGAP+(int16_t)ICON_WIDTH+ (int16_t)ICON_GAP ) |
|
{ |
|
state->position--; |
|
state->frame_position -= ICON_WIDTH + (int16_t)ICON_GAP; |
|
} |
|
else |
|
{ |
|
state->position--; |
|
state->frame_position = ICON_BGAP; |
|
state->menu_start = state->frame_position - state->position*((int16_t)ICON_WIDTH + (int16_t)ICON_GAP); |
|
} |
|
} |
|
} |
|
|
|
|
|
uint8_t towards_int16(int16_t *current, int16_t dest) |
|
{ |
|
if ( *current < dest ) |
|
{ |
|
(*current)++; |
|
return 1; |
|
} |
|
else if ( *current > dest ) |
|
{ |
|
(*current)--; |
|
return 1; |
|
} |
|
return 0; |
|
} |
|
|
|
uint8_t towards(struct menu_state *current, struct menu_state *destination) |
|
{ |
|
uint8_t r = 0; |
|
uint8_t i; |
|
for( i = 0; i < 10; i++ ) |
|
{ |
|
r |= towards_int16( &(current->frame_position), destination->frame_position); |
|
r |= towards_int16( &(current->menu_start), destination->menu_start); |
|
} |
|
return r; |
|
} |
|
|
|
|
|
struct menu_state current_state = { ICON_BGAP, ICON_BGAP, 0 }; |
|
struct menu_state destination_state = { ICON_BGAP, ICON_BGAP, 0 }; |
|
|
|
uint16_t main_menu(void) |
|
{ |
|
button_event = 0; |
|
for(;;) |
|
{ |
|
do |
|
{ |
|
u8g2.firstPage(); |
|
do |
|
{ |
|
main_menu_draw(¤t_state); |
|
u8g2.setFont(MENU_FONT); |
|
u8g2.setCursor((u8g2.getDisplayWidth()-u8g2.getStrWidth(menu_entry_list[destination_state.position].name))/2,u8g2.getDisplayHeight()-7); |
|
u8g2.print(menu_entry_list[destination_state.position].name); |
|
check_button_event(); |
|
delay(20); |
|
} while( u8g2.nextPage() ); |
|
if ( button_event == U8X8_MSG_GPIO_MENU_NEXT ) |
|
main_menu_to_right(&destination_state); |
|
if ( button_event == U8X8_MSG_GPIO_MENU_PREV ) |
|
main_menu_to_left(&destination_state); |
|
if ( button_event == U8X8_MSG_GPIO_MENU_SELECT ) |
|
{ |
|
button_event = 0; |
|
return destination_state.position; |
|
} |
|
if ( button_event > 0 ) // all known events are processed, clear event |
|
button_event = 0; |
|
} while ( towards(¤t_state, &destination_state) ); |
|
} |
|
} |
|
|
|
|
|
/*================================================================================*/ |
|
|
|
int8_t track_bold1_idx = -1; |
|
int8_t track_bold2_idx = -1; |
|
int8_t track_switch[4] = { 0, 0, 0, 0 }; |
|
int16_t track_switch_x[4][2] = { { 85, 85 }, { 9, 19 }, { 58, 58 }, { 105, 105 } }; |
|
int16_t track_switch_y[4][2] = { { 0, 16 }, { 55, 55 }, { 104, 114 }, { 114, 123 } }; |
|
|
|
/* sw=0..3, pos=0..1 */ |
|
void set_swtich(uint8_t sw, uint8_t pos) |
|
{ |
|
uint8_t error; |
|
sw &= 3; |
|
pos &= 1; |
|
Wire.beginTransmission(17); // switch controller |
|
error = Wire.endTransmission(false); |
|
if ( error == 0 ) |
|
{ |
|
Wire.beginTransmission(17); // switch controller |
|
Wire.write(0); |
|
Wire.write(sw*2+pos); |
|
Wire.endTransmission(); |
|
log_line("I2C ok %d, sw=%d/%d", error, sw, pos); |
|
} |
|
else |
|
{ |
|
log_line("I2C err %d, sw=%d/%d", error, sw, pos); |
|
} |
|
} |
|
|
|
|
|
void show_tracks(void) |
|
{ |
|
int i; |
|
int16_t x, y; |
|
u8g2.firstPage(); |
|
do |
|
{ |
|
u8g2.setFont(track_font); |
|
for( i = 0; i < 6; i++ ) |
|
{ |
|
if ( i == track_bold1_idx || i == track_bold2_idx ) |
|
{ |
|
u8g2.drawGlyph(0,128, 'A'+i); |
|
} |
|
else |
|
{ |
|
u8g2.drawGlyph(0,128, 'A'+6+i); |
|
} |
|
} |
|
|
|
check_button_event(); |
|
for( i = 0; i < 4; i++ ) |
|
{ |
|
x = track_switch_x[i][track_switch[i]]; |
|
y = track_switch_y[i][track_switch[i]]; |
|
u8g2.setDrawColor(0); |
|
u8g2.drawBox(x, y, 6, 6); |
|
|
|
u8g2.setDrawColor(1); |
|
u8g2.drawBox(x+1, y+1, 4, 4); |
|
} |
|
|
|
/* |
|
for( i = 0; i < 4; i++ ) |
|
{ |
|
x = track_switch_x[i][1]; |
|
y = track_switch_y[i][1]; |
|
u8g2.setDrawColor(0); |
|
u8g2.drawBox(x, y, 6, 6); |
|
|
|
u8g2.setDrawColor(1); |
|
u8g2.drawBox(x+1, y+1, 4, 4); |
|
} |
|
*/ |
|
|
|
|
|
check_button_event(); |
|
|
|
draw_log(); |
|
} while( u8g2.nextPage() ); |
|
|
|
} |
|
|
|
|
|
void track_switch_test(void) |
|
{ |
|
track_bold1_idx = -1; |
|
track_bold2_idx = -1; |
|
button_event = 0; |
|
for(;;) |
|
{ |
|
show_tracks(); |
|
if ( button_event == U8X8_MSG_GPIO_MENU_NEXT ) |
|
{ |
|
track_switch[3] ^=1; |
|
set_swtich(3, track_switch[3]); |
|
} |
|
if ( button_event == U8X8_MSG_GPIO_MENU_PREV ) |
|
{ |
|
track_switch[1] ^=1; |
|
set_swtich(1, track_switch[1]); |
|
} |
|
if ( button_event == U8X8_MSG_GPIO_MENU_UP ) |
|
{ |
|
track_switch[0] ^=1; |
|
set_swtich(0, track_switch[0]); |
|
} |
|
if ( button_event == U8X8_MSG_GPIO_MENU_DOWN ) |
|
{ |
|
track_switch[2] ^=1; |
|
set_swtich(2, track_switch[2]); |
|
} |
|
if ( button_event == U8X8_MSG_GPIO_MENU_HOME ) |
|
return; |
|
button_event = 0; |
|
} |
|
} |
|
|
|
/*================================================================================*/ |
|
|
|
|
|
/* sw=0..3, pos=0..1 */ |
|
void set_motor_speed(uint8_t motor, uint8_t speed) |
|
{ |
|
uint8_t error; |
|
Wire.beginTransmission(40+motor); // motor controller |
|
error = Wire.endTransmission(false); |
|
if ( error == 0 ) |
|
{ |
|
Wire.beginTransmission(40+motor); // switch controller |
|
Wire.write(0); |
|
Wire.write(speed); |
|
Wire.endTransmission(); |
|
log_line("I2C ok %d, m%d/%d", error, motor, speed); |
|
} |
|
else |
|
{ |
|
log_line("I2C err %d, m%d/%d", error, motor, speed); |
|
} |
|
} |
|
|
|
uint16_t motor_noise_raw; |
|
uint16_t motor_noise_filt; |
|
uint16_t motor_speed_raw; // lower is faster |
|
uint16_t motor_speed_filt; // lower is faster |
|
|
|
void read_motor_data(uint8_t motor) |
|
{ |
|
uint8_t error; |
|
Wire.beginTransmission(40+motor); // motor controller |
|
error = Wire.endTransmission(false); |
|
if ( error == 0 ) |
|
{ |
|
Wire.beginTransmission(40+motor); // motor controller |
|
Wire.write(1); // reset to index 0 |
|
Wire.endTransmission(); |
|
Wire.requestFrom(40+motor, 9); |
|
Wire.read(); // dummy read |
|
motor_noise_raw = Wire.read(); |
|
motor_noise_raw |= (((uint16_t)Wire.read())<<8); |
|
motor_noise_filt = Wire.read(); |
|
motor_noise_filt |= (((uint16_t)Wire.read())<<8); |
|
motor_speed_raw = Wire.read(); |
|
motor_speed_raw |= (((uint16_t)Wire.read())<<8); |
|
motor_speed_filt = Wire.read(); |
|
motor_speed_filt |= (((uint16_t)Wire.read())<<8); |
|
} |
|
} |
|
|
|
void show_motor_set_speed(uint8_t motor, uint8_t speed) |
|
{ |
|
u8g2_uint_t y; |
|
u8g2_uint_t o = 18; |
|
button_event = 0; |
|
|
|
read_motor_data(motor); |
|
|
|
u8g2.firstPage(); |
|
do |
|
{ |
|
check_button_event(); |
|
u8g2.setFont(MENU_FONT); |
|
u8g2.drawBox(5, 0, 2, 128); |
|
u8g2.drawHLine(0, 127-speed/2, 12); |
|
|
|
check_button_event(); |
|
y = (uint8_t)(((uint16_t)(128-o)*(uint16_t)(127-speed/2))>>7); |
|
u8g2.setCursor(14, y+o); |
|
u8g2.print(speed); |
|
check_button_event(); |
|
|
|
u8g2.setCursor(60, 20); |
|
u8g2.print("Motor: "); |
|
u8g2.print(motor); |
|
|
|
u8g2.setFont(SUBMENU_FONT); |
|
u8g2.setCursor(60, 50); |
|
u8g2.print("Noise: "); |
|
u8g2.setCursor(120, 50); |
|
u8g2.print(motor_noise_filt); |
|
|
|
u8g2.setCursor(60, 70); |
|
u8g2.print("Speed: "); |
|
u8g2.setCursor(120, 70); |
|
u8g2.print(motor_speed_filt); |
|
|
|
draw_log(); |
|
} while( u8g2.nextPage() ); |
|
|
|
} |
|
|
|
void motor_speed_test(void) |
|
{ |
|
uint8_t speed[6] = { 128, 128, 128, 128, 128, 128 }; |
|
uint8_t step = 10; |
|
uint8_t motor = 0; |
|
|
|
for( motor = 0; motor < 6; motor++) |
|
set_motor_speed(motor, speed[motor]); |
|
|
|
motor = 0; |
|
for(;;) |
|
{ |
|
show_motor_set_speed(motor, speed[motor]); |
|
|
|
if ( button_event == U8X8_MSG_GPIO_MENU_UP ) |
|
{ |
|
if ( speed[motor] < 128 && speed[motor]+step > 128 ) |
|
speed[motor] = 128; |
|
else if ( speed[motor] < 255-step ) |
|
speed[motor] += step; |
|
else |
|
speed[motor] = 255; |
|
set_motor_speed(motor, speed[motor]); |
|
} |
|
if ( button_event == U8X8_MSG_GPIO_MENU_DOWN ) |
|
{ |
|
if ( speed[motor] > 128 && speed[motor]-step < 128 ) |
|
speed[motor] = 128; |
|
else if ( speed[motor] >= step ) |
|
speed[motor] -=step; |
|
else |
|
speed[motor] = 0; |
|
set_motor_speed(motor, speed[motor]); |
|
} |
|
if ( button_event == U8X8_MSG_GPIO_MENU_SELECT ) |
|
{ |
|
motor++; |
|
if ( motor >= 6 ) |
|
motor = 0; |
|
set_motor_speed(motor, speed[motor]); |
|
} |
|
if ( button_event == U8X8_MSG_GPIO_MENU_HOME ) |
|
{ |
|
button_event = 0; |
|
return; |
|
} |
|
button_event = 0; |
|
} |
|
} |
|
|
|
/*================================================================================*/ |
|
|
|
void loop(void) |
|
{ |
|
uint16_t pos; |
|
pos = main_menu(); |
|
|
|
if ( pos == 0 ) |
|
track_switch_test(); |
|
else if ( pos == 1 ) |
|
motor_speed_test(); |
|
|
|
} |
|
|
|
|