From 50c8981f3896867b6a3455ef1887e090b4420684 Mon Sep 17 00:00:00 2001 From: Ilya Elenskiy Date: Wed, 15 Apr 2020 22:33:28 +0200 Subject: [PATCH] PlatformIO Demo version, Test example --- .gitignore | 8 + README.md | 6 + boards/emgdmm_v3.json | 34 ++ boards/stk500boot.hex | 105 +++++ include/README | 39 ++ include/music.h | 43 ++ lib/README | 46 ++ platformio.ini | 40 ++ src/main.c | 1089 +++++++++++++++++++++++++++++++++++++++++++++ src/music.c | 109 +++++ test/README | 11 + test/test_demo.c | 41 ++ test/unittest_transport.h | 32 ++ 13 files changed, 1603 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 boards/emgdmm_v3.json create mode 100644 boards/stk500boot.hex create mode 100644 include/README create mode 100644 include/music.h create mode 100644 lib/README create mode 100644 platformio.ini create mode 100644 src/main.c create mode 100644 src/music.c create mode 100644 test/README create mode 100644 test/test_demo.c create mode 100644 test/unittest_transport.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7890015 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +depends +.pio +.vscode + +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/README.md b/README.md new file mode 100644 index 0000000..b09e67a --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# DMM Demo + +pio run -t bootloader -e debug +pio run -t upload +pio run test +pio device monitor \ No newline at end of file diff --git a/boards/emgdmm_v3.json b/boards/emgdmm_v3.json new file mode 100644 index 0000000..f566bbf --- /dev/null +++ b/boards/emgdmm_v3.json @@ -0,0 +1,34 @@ +{ + "build": { + "f_cpu": "16000000L", + "hwids": [ + [ + "0x0403", + "0x6001" + ] + ], + "mcu": "atmega1284p" + }, + "platforms": [ + "atmelavr" + ], + "name": "EMG DMM Board", + "upload": { + "maximum_ram_size": 16384, + "maximum_size": 126976, + "protocol": "stk500", + "require_upload_port": true + }, + "bootloader": { + "file": "boards/stk500boot.hex", + "lfuse": "0xDE", + "hfuse": "0x98", + "efuse": "0xFF", + "lock_bits": "0xFF" + }, + "test": { + "speed": 9600 + }, + "url": "https://www.emg.tu-bs.de/lehre/vl/vl_dmm_d.html", + "vendor": "EMG, TU braunschweig" +} \ No newline at end of file diff --git a/boards/stk500boot.hex b/boards/stk500boot.hex new file mode 100644 index 0000000..420ca57 --- /dev/null +++ b/boards/stk500boot.hex @@ -0,0 +1,105 @@ +:020000021000EC +:10F800008FEF90E49EBF8DBF11241FBE00C0CDB707 +:10F81000DEB7C852D140DEBFCDBF81B1877081B99C +:10F8200082B1886F82B99FE094B985B18F6085B944 +:10F830000699BEC294B98EE085B98091C0008260FD +:10F840008093C00080E190E09093C5008093C40055 +:10F8500088E18093C10088249924540144245524CC +:10F8600032012224332460E0C05EDE4F1882C05291 +:10F87000D14021E0C15EDE4F2883CF51D14042E02C +:10F8800050E04C0F5D1F4E5F5F4FC95DDE4F5983E7 +:10F890004883C752D14088C22B988091C00087FF0F +:10F8A000FCCF85B1A8E08A2785B93091C600933096 +:10F8B000A9F1943028F4913079F0923050F507C0D6 +:10F8C0009530D1F1953088F1963031F747C03B3112 +:10F8D00019F791E06BE1E0CF313071F0C15EDE4F9E +:10F8E000B881CF51D140BB2339F4C05EDE4FE881EF +:10F8F000C052D1403E17A9F56327C05EDE4F388362 +:10F90000C052D14092E0C15EDE4F1882CF51D1404B +:10F91000C3CF532F40E0632793E0BECF832F90E007 +:10F92000482B592B632794E0B7CF3E30D1F463279F +:10F9300095E022243324B0CFE2E0F0E0EC0FFD1F8D +:10F94000E20DF31D30830894211C311C632724161B +:10F95000350609F0A1CFA10196E09ECF361709F434 +:10F9600030C290E099CF299A1B82F8E0FC8323E50E +:10F970002D8384E58E838BE48F8385E3888780E302 +:10F9800089878A878FE58B8782E38C874BE050E0FD +:10F9900096C119828B81813991F0823938F481388E +:10F9A000B1F0803951F0803899F411C0843961F098 +:10F9B000853969F0823961F405C08FE006C032E014 +:10F9C000398306C08AE001C082E3898301C01982BD +:10F9D0001B8289818C8343E050E071C18E81882332 +:10F9E00011F48EE12CC0813011F085E028C087E948 +:10F9F00026C01B8229E0E1E0F0E0209357008491CB +:10FA00008C831D8244E050E05AC18C81803589F49A +:10FA10008D81883039F429E0E2E0F0E0209357004E +:10FA200084910DC029E0E0E0F0E02093570084913C +:10FA300006C029E0E3E0F0E02093570084911B82A8 +:10FA4000DFCF80E090E0A0E0B0E033E0FC01A093E5 +:10FA50005B0030935700E89507B600FCFDCF80505F +:10FA60009F4FAF4FBF4F80304CEF940740E0A4074B +:10FA700040E0B40751F71B824424552432011DC1D4 +:10FA80008B8190E0A0E0B0E0B82EAA2499248824CD +:10FA90008C8190E0A0E0B0E0DC0199278827882ADB +:10FAA000992AAA2ABB2A8E8190E0A0E0B0E0882A99 +:10FAB000992AAA2ABB2A8D8190E0A0E0B0E0BA2F53 +:10FAC000A92F982F8827882A992AAA2ABB2A880C26 +:10FAD000991CAA1CBB1C1B82F0C05FEF45165BEF94 +:10FAE000550650E0650650E0750690F483E0F2019B +:10FAF00060925B0080935700E89507B600FCFDCF4D +:10FB000020E031E040E050E0420E531E641E751EBE +:10FB1000B501A4018E01045F1F4FF801808121818E +:10FB20000E5F1F4FCC5DDE4F2883C452D140CD5DA8 +:10FB3000DE4F1882C352D14090E0CD5DDE4F288168 +:10FB40003981C352D140822B932B31E00C01FA0151 +:10FB500060935B0030935700E89511244E5F5F4F30 +:10FB60006F4F7F4F1297C9F685E0F401A0925B00BA +:10FB700080935700E89507B600FCFDCF91E1909384 +:10FB80005700E89525C0B501A401FE013C961197E8 +:10FB90008D0120E030E00F5F1F4F2F4F3F4F080DCA +:10FBA000191D2A1D3B1D41BDBB27A72F962F852F51 +:10FBB00082BD4F5F5F4F6F4F7F4F819180BDFA9A3B +:10FBC000F99AF999FECF401751076207730759F761 +:10FBD0001B822A984A015B0170C0AB81CA5DDE4F6F +:10FBE000A883C652D140CB5DDE4F1882C552D140AA +:10FBF0008C81C82EDD24CB5DDE4FE881F981C552B2 +:10FC0000D140CE2ADF2A1B828A818431F9F4A601F1 +:10FC1000C95DDE4FE880F980C752D140ABBEF40128 +:10FC200087919691D7018C9311969C93E2E0F0E036 +:10FC3000EE0EFF1E82E090E0A0E0B0E0880E991E7C +:10FC4000AA1EBB1E4250504049F72FC0B501A40167 +:10FC5000C95DDE4FE880F980C752D1400894C108E1 +:10FC6000D108860120E030E00894C11CD11C0F5F50 +:10FC70001F4F2F4F3F4F080D191D2A1D3B1D41BD22 +:10FC8000BB27A72F962F852F82BD4F5F5F4F6F4FEA +:10FC90007F4FF89A80B5D7018D937D0140175107AA +:10FCA0006207730761F74A015B01A6014D5F5F4F71 +:10FCB000F701108204C080EC8B8342E050E0FBE14E +:10FCC000F093C6008091C00086FFFCCF8091C000F9 +:10FCD00080648093C000C05EDE4F2881C052D14056 +:10FCE0002093C6008091C00086FFFCCF8091C000A9 +:10FCF00080648093C000352F5093C6008091C0006F +:10FD000086FFFCCF8091C00080648093C000942F58 +:10FD10004093C6008091C00086FFFCCF8091C00058 +:10FD200080648093C0008EE08093C6008091C00004 +:10FD300086FFFCCF8091C00080648093C00065E1A5 +:10FD4000C05EDE4F8881C052D14068276927632793 +:10FD5000FE01329610C090819093C6008091C00041 +:10FD600086FFFCCF31968091C00080648093C000F4 +:10FD70006927415050404115510569F76093C6000D +:10FD80008091C00086FFFCCF8091C000806480938A +:10FD9000C000C05EDE4F9881C052D1409F5FC05E00 +:10FDA000DE4F9883C052D14090E040E050E074CDE7 +:10FDB00081E180935700E89511241F921F920895C6 +:10FDC000FFCF9A81923109F43CCE9331B0F4933055 +:10FDD00009F4DFCD943038F4913009F4C4CD923079 +:10FDE00009F069CF78CE963009F44ACE963008F4FF +:10FDF00062CF903108F45FCF6ECE963109F4EDCE2C +:10FE00009731F0F4943109F4E8CEAB81CE5DDE4F4A +:10FE1000A883C252D140CF5DDE4F1882C152D1407B +:10FE20008C81A82FB0E0CF5DDE4FE881F981C1520F +:10FE3000D140AE2BBF2B2A9A933109F0A4CE4DCEE0 +:10FE40009A3109F4D6CD9B3109F4C8CD983109F027 +:04FE500032CFDBCD05 +:040000031000F800F1 +:00000001FF 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/include/music.h b/include/music.h new file mode 100644 index 0000000..295596a --- /dev/null +++ b/include/music.h @@ -0,0 +1,43 @@ +#ifndef MUSIC_H_ +#define MUSIC_H_ + +typedef struct +{ + uint16_t tone; + uint16_t duration; +} MUSIC_Note; + +#define MUSIC_END { 0, 0 } +#define MUSIC_IS_END(_note_) (!((_note_).tone) && !((_note_).duration)) + +#define MUSIC_A4 440 +#define MUSIC_B4 494 +#define MUSIC_C4 262 +#define MUSIC_D4 293 +#define MUSIC_E4 330 +#define MUSIC_F4 349 +#define MUSIC_G4 392 + +#define MUSIC_A5 880 +#define MUSIC_B5 988 +#define MUSIC_C5 523 +#define MUSIC_D5 587 +#define MUSIC_E5 659 +#define MUSIC_F5 698 +#define MUSIC_G5 784 + +#define MUSIC_1 1000 +#define MUSIC_2 (MUSIC_1/2) +#define MUSIC_4 (MUSIC_1/4) +#define MUSIC_8 (MUSIC_1/8) +#define MUSIC_16 (MUSIC_1/16) +#define MUSIC_32 (MUSIC_1/32) + + +typedef const MUSIC_Note* MUSIC_Track; +extern const MUSIC_Note MUSIC_Tetris[]; + +void Music_PlayTrack (MUSIC_Track track); + + +#endif /* MUSIC_H_ */ \ No newline at end of file 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 +#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/platformio.ini b/platformio.ini new file mode 100644 index 0000000..0d8fbcd --- /dev/null +++ b/platformio.ini @@ -0,0 +1,40 @@ +; 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 + +[platformio] +default_envs = release +libdeps_dir = depends + +[env] +platform = atmelavr +board = emgdmm_v3 + +test_transport = custom +test_speed = 9600 + +lib_deps = + git@teach.emg.ing.tu-bs.de:dmm/dmm-libs.git + +[env:release] ; for flash via bootloader +; keep defaults, see board definitions for programming support + + +[env:debug] ; for JTAG bootloader flashing and potentialy debugging once supported +build_type = debug +build_flags = -D DEBUG + +upload_protocol = jtag3 +upload_flags = -p, atmega1284 ; fix signature error with JTAGICE + +; Atmel-ICE based AVR debug is not directly supported by PIO as of 04.2020. As not +; available at home, not an issue for DMM at the moment. +; Potentially solveable by using avarice as a server. +; See: https://github.com/platformio/platform-atmelavr/issues/53 + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..41a481f --- /dev/null +++ b/src/main.c @@ -0,0 +1,1089 @@ +#include +#include +#include +#include +#include +#include + +#include "uart.h" +#include "lcd.h" +#include "twi.h" +#include "dataflash.h" +#include "music.h" + +#define wait_joy_button() \ + { \ + LCD_GotoXY(20, 7); \ + LCD_PutChar(0x10); \ + LCD_Update(); \ + while (((PINA)&0x08)) \ + ; \ + while (!((PINA)&0x08)) \ + ; \ + _delay_ms(20); \ + while (((PINA)&0x08)) \ + ; \ + } + +const uint8_t PROGMEM emg_logo[640] = + { + 0x80, + 0xe0, + 0xf0, + 0xf8, + 0xf8, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xf8, + 0xf8, + 0xf0, + 0xe0, + 0x80, + 0x00, + 0x00, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xf0, + 0xf8, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xf8, + 0xf8, + 0xf0, + 0xe0, + 0xc0, + 0xe0, + 0xf0, + 0xf8, + 0xf8, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xf8, + 0xf8, + 0xf0, + 0xe0, + 0x80, + 0x00, + 0x00, + 0x80, + 0xe0, + 0xf0, + 0xf8, + 0xf8, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xf8, + 0xf8, + 0xf0, + 0xe0, + 0x80, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xf7, + 0xf3, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf1, + 0xf7, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x1f, + 0x07, + 0x03, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x03, + 0x0f, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x07, + 0x03, + 0x03, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x03, + 0x07, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x1f, + 0x03, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x03, + 0x07, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xf1, + 0xe1, + 0xc1, + 0xc1, + 0x81, + 0x81, + 0x81, + 0x81, + 0xc1, + 0xc1, + 0xc1, + 0xc1, + 0xc1, + 0xc1, + 0xe1, + 0xe1, + 0xe1, + 0xe1, + 0xe1, + 0xe1, + 0xe1, + 0xe1, + 0xe1, + 0xe1, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xf0, + 0xe0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xc0, + 0xe0, + 0xf0, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x01, + 0x07, + 0x07, + 0x0f, + 0x0f, + 0x0f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x0f, + 0x0f, + 0x0f, + 0x07, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x03, + 0x07, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x0f, + 0x8f, + 0xcf, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x1f, + 0x0f, + 0x07, + 0x01, +}; + +void demo_backlight(void); +void demo_start(void); +void demo_display(void); +void demo_show_emg(void); +void demo_uart(void); +void demo_music(void); + +int main(void) +{ + // set PA3-PA7 as input and activated internal Pull-Up + DDRA &= ~((1 << PINA3) | (1 << PINA4) | (1 << PINA5) | (1 << PINA6) | (1 << PINA7)); // Required for DMM Board 2013 + PORTA |= ((1 << PINA3) | (1 << PINA4) | (1 << PINA5) | (1 << PINA6) | (1 << PINA7)); // Required for DMM Board 2013 + + // set PB0-PB3 as output + DDRB = 0x0F; + // set PB0-PB3 on high-level + PORTB |= 0x0F; // Required for DMM Board DMM Board 2013 + + LCD_Init(); + UART_Init(); + + demo_start(); + demo_show_emg(); + + demo_uart(); + demo_display(); + demo_backlight(); + demo_music(); + + Backlight_Off(); + LCD_Clear(); + + // loop forever + while (1) + ; +} + +void demo_start(void) +{ + // Turn on green backlight + Backlight_LED(BL_GREEN_ON); + + // Place program memory strings in framebuffer + LCD_PutString_P(PSTR("-DMM AVR-Board Demo- \r\n\n")); + LCD_PutString_P(PSTR("Always push the \r\n")); + LCD_PutString_P(PSTR("joystick button to \r\n")); + LCD_PutString_P(PSTR("proceed to the next \r\n")); + LCD_PutString_P(PSTR("screen. \r\n\n")); + LCD_PutString_P(PSTR("Enjoy the demo! ")); + + // Copy framebuffer to display + LCD_Update(); + + // Wait for joystick button + wait_joy_button(); +} + +void demo_show_emg(void) +{ + // Some counters + uint16_t emg_offset = 0; + uint8_t fb_x; + uint8_t fb_y; + + // Turn on white backlight (red, green and blue) + Backlight_LED(BL_RED_ON | BL_GREEN_ON | BL_BLUE_ON); + + // Clear precautionally + LCD_Clear(); + + // Copy emglogo into framebuffer + for (fb_y = 0; fb_y < 5; fb_y++) + for (fb_x = 0; fb_x < 128; fb_x++) + lcd_framebuffer[fb_y][fb_x] = pgm_read_byte(&emg_logo[emg_offset++]); + + // Mark pages 0-4 for update + lcd_frameupdate = 0x1f; + + // Add some text + LCD_GotoXY(0, 5); + LCD_PutString_P(PSTR(" Institut f\x81r Messt. \r\n")); + LCD_PutString_P(PSTR(" und Grundlagen der \r\n")); + LCD_PutString_P(PSTR(" Elektrotechnik \r\n")); + + // And copy framebuffer to display + LCD_Update(); + + wait_joy_button(); +} + +void demo_uart(void) +{ + unsigned char loop = 1; + signed int c; + char buffer[10]; + + LCD_Clear(); + Backlight_LED(BL_BLUE_ON); + + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("UART-Demonstration \r\n\n")); + LCD_PutString_P(PSTR("Setup your terminal: \r\n")); + LCD_PutString_P(PSTR("9600 Baud, 8N1 \r\n")); + LCD_PutString_P(PSTR("Use joystick to send \r\n")); + LCD_PutString_P(PSTR("some strings. \r\n")); + + LCD_GotoXY(20, 7); + LCD_PutChar(0x10); + + LCD_Update(); + + while ((!((PINA)&0x08))) + ; + _delay_ms(20); + while (!((PINA)&0x08)) + ; + + while (loop) + { + // Get net character from uart fifo + c = UART_GetChar(); + + // c = -1 means fifo empty + if (c > -1) + { + // wipe last lcd line + LCD_WipeLine(7); + + LCD_GotoXY(0, 7); + LCD_PutString_P(PSTR("RX-ASCII-Code: ")); + // Convert interger to ascii + itoa(c, buffer, 10); + + LCD_PutString(buffer); + LCD_GotoXY(20, 7); + LCD_PutChar(0x10); + LCD_Update(); + _delay_ms(10); + } + + _delay_ms(20); + while (!((PINA)&0xF8)) + ; // Different to DMM 2012 and before + + switch (((PINA)&0xF8)) + { + case 0x78: + // Joystick Up + UART_PutString("Joystick Up.\r\n"); + break; + case 0xB8: + // Joystick Down + UART_PutString("Joystick Down.\r\n"); + break; + case 0xD8: + // Joystick Left + UART_PutString("Joystick Left.\r\n"); + break; + case 0xE8: + // Joystick Right + UART_PutString("Joystick Right.\r\n"); + break; + case 0xF0: + // Joystick Button + UART_PutString("Exit.\r\n\n"); + loop = 0; + break; + } + + _delay_ms(200); + } +} + +void demo_music(void) +{ + LCD_Clear(); + Backlight_LED(BL_RED_ON); + + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Let's dance!\r\n\n")); + LCD_PutString_P(PSTR("(Finest PWM sounds!)\r\n\n")); + LCD_Update(); + + Music_PlayTrack(MUSIC_Tetris); + + LCD_PutString_P(PSTR("OK, that's enough...\r\n\n")); + LCD_Update(); + + wait_joy_button(); +} + +void demo_display(void) +{ + // switch white backlight on + Backlight_LED(BL_RED_ON | BL_GREEN_ON | BL_BLUE_ON); + + // clear display + LCD_Clear(); + + // talking to the user + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Set some pixels.")); + + LCD_DrawPixel(10, 10, 1); + LCD_DrawPixel(12, 44, 1); + LCD_DrawPixel(111, 62, 1); + LCD_DrawPixel(101, 22, 1); + LCD_Update(); + + wait_joy_button(); + + // one display page requires 8 pages in dataflash + LCD_SavePage(0); + LCD_WipeLine(0); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Connecting.")); + + LCD_DrawLine(10, 10, 12, 44, 1); + LCD_DrawLine(12, 44, 111, 62, 1); + LCD_DrawLine(111, 62, 101, 22, 1); + LCD_DrawLine(101, 22, 10, 10, 1); + LCD_Update(); + + wait_joy_button(); + + // first display page was stored at flash page 0 + // second display page will start at 8 + LCD_SavePage(8); + LCD_WipeLine(0); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Adding circles.")); + + LCD_DrawCircle(64, 32, 10, 1); + LCD_DrawCircle(70, 30, 20, 1); + LCD_Update(); + + wait_joy_button(); + + // talking to the user + LCD_SavePage(16); + LCD_Clear(); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Clear/Set/XOR Demo.")); + + for (unsigned int fill = 0; fill < 128; fill++) + LCD_DrawLine(fill, 10, fill, 53, (fill / 8) & 1); + + // Clear + LCD_DrawLine(0, 20, 127, 20, 0); + + // Set + LCD_DrawLine(0, 30, 127, 30, 1); + + // XOR + LCD_DrawLine(0, 40, 127, 40, 2); + + LCD_Update(); + + wait_joy_button(); + + // talking to the user + LCD_SavePage(24); + LCD_Clear(); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Use the joystick to\r\n")); + LCD_PutString_P(PSTR("recall the last\r\n")); + LCD_PutString_P(PSTR("screens. Again,\r\n")); + LCD_PutString_P(PSTR("button means exit.\r\n")); + LCD_Update(); + + unsigned char loop = 1; + + while (loop) + { + // wait + while ((!((PINA)&0xF8))) + ; // Different to DMM 2012 and before + _delay_ms(300); + while (!((PINA)&0xF8)) + ; // Different to DMM 2012 and before + + switch ((~PINA) & 0xF8) // Different to DMM 2012 and before + { + case 0x80: + // UP + LCD_LoadPage(0); + LCD_WipeLine(0); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Screen 1")); + LCD_Update(); + break; + case 0x40: + // DOWN + LCD_LoadPage(24); + LCD_WipeLine(0); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Screen 4")); + LCD_Update(); + break; + case 0x20: + // LEFT + LCD_LoadPage(8); + LCD_WipeLine(0); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Screen 2")); + LCD_Update(); + break; + case 0x10: + // RIGHT + LCD_LoadPage(16); + LCD_WipeLine(0); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Screen 3")); + LCD_Update(); + break; + case 0x08: + // BUTTON + loop = 0; + break; + } + } + + // talking to the user + LCD_Clear(); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Push button for\r\n")); + LCD_PutString_P(PSTR("next demonstration.\r\n")); + + wait_joy_button(); +} + +void demo_backlight(void) +{ + unsigned char led_active = 0x80; + + // white backlight + Backlight_LED(BL_RED_ON | BL_GREEN_ON | BL_BLUE_ON); + + LCD_Clear(); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR("Use the joystick to\r\n")); + LCD_PutString_P(PSTR("toggle the backlight\r\n")); + LCD_PutString_P(PSTR("on the next screen.")); + LCD_Update(); + + wait_joy_button(); + + // no backlight + Backlight_Off(); + + LCD_Clear(); + LCD_GotoXY(0, 0); + LCD_PutString_P(PSTR(" Red \r\n")); + LCD_PutString_P(PSTR(" \r\n")); + LCD_PutString_P(PSTR(" \x18 \r\n")); + LCD_PutString_P(PSTR(" Green \x1b Exit \x1a Blue \r\n")); + LCD_PutString_P(PSTR(" \x19 \r\n")); + LCD_PutString_P(PSTR(" \r\n")); + LCD_PutString_P(PSTR(" Toggle \r\n")); + LCD_PutString_P(PSTR(" all \x10\r\n")); + LCD_Update(); + + while (!((PINA)&0x08)) + ; + _delay_ms(20); + while (!((PINA)&0x08)) + ; + + while (led_active & 0x80) + { + + while ((~(PINA)&0xF8)) + ; // Different to DMM 2012 and before + _delay_ms(300); + while (!((PINA)&0xF8)) + ; // Different to DMM 2012 and before + + switch ((~PINA) & 0xF8) // Different to DMM 2012 and before + { + case 0x08: + // Button -> Exit + led_active = 0x00; + + break; + case 0x80: + // Up -> Toggle Red + led_active ^= 0x01; + break; + case 0x20: + // Up -> Toggle Green + led_active ^= 0x04; + break; + case 0x10: + // Up -> Toggle Blue + led_active ^= 0x10; + break; + case 0x40: + // Up -> Toggle All + led_active ^= 0x15; + break; + } + + while (!(PINA & 0xf8)) + ; + + Backlight_LED(led_active & 0x15); + + PORTB &= ~0x0f; + if (led_active & 0x01) + PORTB |= 0x01; + if (led_active & 0x04) + PORTB |= 0x02; + if (led_active & 0x10) + PORTB |= 0x04; + } + + LCD_Clear(); +} diff --git a/src/music.c b/src/music.c new file mode 100644 index 0000000..5f30063 --- /dev/null +++ b/src/music.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include + +#include "music.h" + +/* Sine lookup table for the PWM generator (pp = 32) */ +static const PROGMEM unsigned char sine_lookup[]={ + 0x10,0x13,0x16,0x19,0x1b,0x1d,0x1f,0x20, + 0x20,0x20,0x1f,0x1d,0x1b,0x19,0x16,0x13, + 0x10,0x0d,0x0a,0x07,0x05,0x03,0x01,0x00, + 0x00,0x00,0x01,0x03,0x05,0x07,0x0a,0x0d +}; + +const MUSIC_Note MUSIC_Tetris[] = { + { MUSIC_E5, MUSIC_4 }, + { MUSIC_B4, MUSIC_8 }, + { MUSIC_C5, MUSIC_8 }, + { MUSIC_D5, MUSIC_4 }, + { MUSIC_C5, MUSIC_8 }, + { MUSIC_D5, MUSIC_8 }, + + { MUSIC_A4, MUSIC_4 }, + { MUSIC_A4, MUSIC_8 }, + { MUSIC_C5, MUSIC_8 }, + { MUSIC_E5, MUSIC_4 }, + { MUSIC_D5, MUSIC_8 }, + { MUSIC_C5, MUSIC_8 }, + + { MUSIC_B4, MUSIC_4 + MUSIC_8 }, + { MUSIC_C5, MUSIC_8 }, + { MUSIC_D5, MUSIC_4 }, + { MUSIC_E5, MUSIC_4 }, + + { MUSIC_C5, MUSIC_4 }, + { MUSIC_A4, MUSIC_4 }, + { MUSIC_A4, MUSIC_8 }, + + MUSIC_END }; + +static void delay_ms(uint16_t delay); +static void pwm_init (void); +static void pwm_deinit (void); +static void pwm_gen(uint16_t tone, uint16_t periods); + +void Music_PlayTrack (MUSIC_Track track) +{ + pwm_init(); + + while (!MUSIC_IS_END(*track)) { + + if (track->tone == 0) { + delay_ms(track->duration); + } else { + uint16_t periods = (uint32_t)track->duration * (uint32_t)track->tone / 1000; + pwm_gen(track->tone, periods); + + delay_ms(MUSIC_32 / 2); + } + + ++track; + } + + pwm_deinit(); +} + +static void delay_ms(uint16_t delay) +{ + while (delay--) + _delay_ms(1); +} + +void pwm_init (void) +{ + //setup PWM timer + DDRD |= _BV(PIND5); // speaker pin => output + TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM10); //set on match + TCCR1B = _BV(CS10) | _BV(WGM12); //fast PWM (8 bit), clk/1 source + + //setup sample timer (CTC Mode) + TCCR3A = 0; + TCCR3B = _BV(CS30) | _BV(WGM32); // clk/1 +} + +void pwm_deinit (void) +{ + TCCR1A = 0; + TCCR1B = 0; + TCCR3A = 0; + TCCR3B = 0; +} + +void pwm_gen(uint16_t tone, uint16_t periods) +{ + //calculate single sine sample duration + OCR3A = F_CPU / tone / sizeof(sine_lookup) - 1; + + for (uint16_t period=0; period < periods; ++period) { + for (uint8_t spl=0; spl < sizeof(sine_lookup); ++spl) { + //wait for timer ready for next spl + loop_until_bit_is_set(TIFR3, OCF1A); + TIFR3 = _BV(OCF1A); //clear OCF + + OCR1A = pgm_read_byte(sine_lookup + spl) + 0x70; + } + } +} \ No newline at end of file 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 diff --git a/test/test_demo.c b/test/test_demo.c new file mode 100644 index 0000000..961001f --- /dev/null +++ b/test/test_demo.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include "fifo.h" + +#include "unittest_transport.h" + +void test_fifo(void) +{ + uint8_t buf[3]; + fifo_t f; + fifo_init(&f, buf, sizeof(buf)); + fifo_put(&f, 0x11); + fifo_put(&f, 0x22); + fifo_put(&f, 0x33); + + TEST_ASSERT_EQUAL(fifo_get_nowait(&f), 0x11); + TEST_ASSERT_EQUAL(fifo_get_nowait(&f), 0x22); + TEST_ASSERT_EQUAL(fifo_get_nowait(&f), 0x33); +} + +int main() +{ + // NOTE!!! Wait for >2 secs + // if board doesn't support software reset via Serial.DTR/RTS + _delay_ms(2000); + + DDRB |= 0x2; + PORTB &= ~0x2; + + UNITY_BEGIN(); // IMPORTANT LINE! + RUN_TEST(test_fifo); + UNITY_END(); // stop unit testing + + PORTB |= 0x2; + DDRB |= 0x4; + PORTB &= ~0x4; + + while (1) + ; +} diff --git a/test/unittest_transport.h b/test/unittest_transport.h new file mode 100644 index 0000000..f01e01c --- /dev/null +++ b/test/unittest_transport.h @@ -0,0 +1,32 @@ +#ifndef UNITTEST_TRANSPORT_H +#define UNITTEST_TRANSPORT_H + +#include +#include +#include "uart.h" + +void unittest_uart_begin() +{ + // Set Baudrate according to datasheet (16MHz -> 9600 Baud -> 103) + UBRR0 = 103; + UCSR0B |= (1<