commit 4f390025341d124540a281b1f15f605e008506ed Author: MultiMote Date: Sun Jan 1 18:21:01 2023 +0300 Первый коммит diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d92f2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +resources/_gen \ No newline at end of file diff --git a/.hugo_build.lock b/.hugo_build.lock new file mode 100644 index 0000000..e69de29 diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..30632a0 --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,13 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +categories: ["misc"] + +--- + +Описание + + + +Текст \ No newline at end of file diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..dab7034 --- /dev/null +++ b/config.toml @@ -0,0 +1,15 @@ +baseURL = 'https://mmote.ru/' +title = 'Здесь был MultiMote' +theme = 'mmotium' +languageCode = 'ru' + +[params] + author = 'MultiMote' + +[permalinks] + posts = "/:slugorfilename" + other = "/:slugorfilename" + +[markup] + [markup.highlight] + style = 'monokailight' \ No newline at end of file diff --git a/content/categories/archive/_index.md b/content/categories/archive/_index.md new file mode 100644 index 0000000..6aaf78e --- /dev/null +++ b/content/categories/archive/_index.md @@ -0,0 +1,4 @@ +--- +title: "Архив" +description: "Это было давно и неправда" +--- \ No newline at end of file diff --git a/content/categories/cpp/_index.md b/content/categories/cpp/_index.md new file mode 100644 index 0000000..6e7c26e --- /dev/null +++ b/content/categories/cpp/_index.md @@ -0,0 +1,3 @@ +--- +title: "Программирование на C/C++" +--- \ No newline at end of file diff --git a/content/categories/dendrite-fecal/_index.md b/content/categories/dendrite-fecal/_index.md new file mode 100644 index 0000000..e0347ba --- /dev/null +++ b/content/categories/dendrite-fecal/_index.md @@ -0,0 +1,3 @@ +--- +title: "Дендрофекальное проектирование" +--- \ No newline at end of file diff --git a/content/categories/mcu/_index.md b/content/categories/mcu/_index.md new file mode 100644 index 0000000..b25fb79 --- /dev/null +++ b/content/categories/mcu/_index.md @@ -0,0 +1,3 @@ +--- +title: "Микроконтроллеры" +--- \ No newline at end of file diff --git a/content/categories/misc/_index.md b/content/categories/misc/_index.md new file mode 100644 index 0000000..d8575da --- /dev/null +++ b/content/categories/misc/_index.md @@ -0,0 +1,3 @@ +--- +title: "Разное" +--- \ No newline at end of file diff --git a/content/categories/news/_index.md b/content/categories/news/_index.md new file mode 100644 index 0000000..d0ea655 --- /dev/null +++ b/content/categories/news/_index.md @@ -0,0 +1,3 @@ +--- +title: "Новости" +--- \ No newline at end of file diff --git a/content/categories/pinned/_index.md b/content/categories/pinned/_index.md new file mode 100644 index 0000000..9294120 --- /dev/null +++ b/content/categories/pinned/_index.md @@ -0,0 +1,4 @@ +--- +title: "Закреплено" +description: "Информация особой важности" +--- \ No newline at end of file diff --git a/content/other/astyle-style/index.md b/content/other/astyle-style/index.md new file mode 100644 index 0000000..c484927 --- /dev/null +++ b/content/other/astyle-style/index.md @@ -0,0 +1,18 @@ +--- +title: "Astyle" +categories: ["cpp", "archive"] +date: 2018-08-31T00:00:00+03:00 +draft: false +--- + + + + +``` +--style=java +--pad-oper +--pad-header +--convert-tabs +--align-pointer=name +--align-reference=name +``` \ No newline at end of file diff --git a/content/other/avr-runline/anim.gif b/content/other/avr-runline/anim.gif new file mode 100644 index 0000000..7a98764 Binary files /dev/null and b/content/other/avr-runline/anim.gif differ diff --git a/content/other/avr-runline/index.md b/content/other/avr-runline/index.md new file mode 100644 index 0000000..b5ef094 --- /dev/null +++ b/content/other/avr-runline/index.md @@ -0,0 +1,68 @@ +--- +title: "Бегущая строка" +categories: ["mcu", "archive"] +date: 2016-02-19T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + + + +```c +#include +#include +#include +#include "lcd_lib.h" + +#define LINE 16 + +char *str = "Postapokaliptichesky1232323123"; +char *pstr; +char buf[LINE + 1]; + +void lcd_clear() { + LCDsendCommand(0x01); +} + +void lcd_zero_coord() { + char y = 0; + char x = 0; + LCDsendCommand(0x80 | ((0x40 * y) + x)); +} + +void lcd_data(char byte) { + LCDsendChar(byte); +} + +void lcd_str(char *s) { + while (*s != '\0') lcd_data(*(s++)); +} + + +int main(void) { + LCDinit(); + lcd_clear(); + while (1) { + int len = strlen(str) + LINE; + for (int i = 0; i < len; ++i) { + lcd_clear(); + lcd_zero_coord(); + + strcpy(buf, str); + int spaces = LINE - i; + + buf[i] = '\0'; + pstr = buf; + + if (spaces > 0) for (int s = 0; s < spaces; ++s) lcd_data(' '); + else pstr += i - LINE; + + lcd_str(pstr); + _delay_ms(100); + } + } +} +``` + +![|](anim.gif) \ No newline at end of file diff --git a/content/other/avr-runline/miniature.jpg b/content/other/avr-runline/miniature.jpg new file mode 100644 index 0000000..b76bb48 Binary files /dev/null and b/content/other/avr-runline/miniature.jpg differ diff --git a/content/other/cheatsheet/index.md b/content/other/cheatsheet/index.md new file mode 100644 index 0000000..6ef55a4 --- /dev/null +++ b/content/other/cheatsheet/index.md @@ -0,0 +1,107 @@ +--- +title: "Полезности" +categories: ["cpp", "archive"] +date: 2015-12-01T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +На этой страничке я собираю все полезные кусочки кодов, которые мне пригождаются. + + + +# С/С++: + + +## Вывод списка файлов в папке, dirent: + +```c +DIR *dir; +struct dirent *ent; +if (dir = opendir ("mydir")) { + while (ent = readdir (dir)) { + printf ("%s\n", ent->d_name); + } + closedir (dir); +} +``` + +## Удаление элементов вектора во время итерации: + +```cpp +vector< string >::iterator it = curFiles.begin(); + +while(it != curFiles.end()) { + if(something) { + it = curFiles.erase(it); + } else ++it; +} +``` + +## Освобождение памяти вектора: + +```cpp +struct delete_ptr { + template + void operator () (P p) { + delete p; + } +}; + +std::for_each(myvector.begin(), myvector.end(), delete_ptr()); +myvector.clear(); +``` + +## Построковое чтение файла: + +```c +const char filename[] = "file.txt"; +FILE *file = fopen(filename, "r"); +if (file != NULL) { + char line[128]; + while (fgets(line, sizeof line, file) != NULL) + { + fputs(line, stdout); + } + fclose(file); +} +``` + +## OpenGL, рисование цветных прямоугольников: + +```cpp +void drawRect(int x1, int y1, int x2, int y2, int color) { + float alpha = (float) (color >> 24 & 255) / 255.0F; + float red = (float) (color >> 16 & 255) / 255.0F; + float green = (float) (color >> 8 & 255) / 255.0F; + float blue = (float) (color & 255) / 255.0F; + glColor4f(red, green, blue, alpha); + glBegin(GL_QUADS); + glVertex3f(x1, y2, 0.0F); + glVertex3f(x2, y2, 0.0F); + glVertex3f(x2, y1, 0.0F); + glVertex3f(x1, y1, 0.0F); + glEnd(); +} + +void drawRectAt(int x, int y, int width, int height, int color) { + drawRect(x, y, x + width, x + height, color); +} + +void drawPixel(int x, int y, int color) { + drawRect(x, y, x + 1, y + 1, color); +} +``` + +## Количество дней в месяце (с учётом високостного года): + +```c +int get_month_days(int year, int month){ + if (month == 4 || month == 6 || month == 9 || month == 11){ + return 30; + } else if (month == 2) { + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 29 : 28; + } else return 31; +} +``` diff --git a/content/other/cheatsheet/miniature.jpg b/content/other/cheatsheet/miniature.jpg new file mode 100644 index 0000000..ea709d2 Binary files /dev/null and b/content/other/cheatsheet/miniature.jpg differ diff --git a/content/other/cleanup-open-with/index.md b/content/other/cleanup-open-with/index.md new file mode 100644 index 0000000..9afb312 --- /dev/null +++ b/content/other/cleanup-open-with/index.md @@ -0,0 +1,12 @@ +--- +title: "Удаление программ из меню " +categories: ["misc", "archive"] +date: 2018-07-03T00:00:00+03:00 +draft: false +--- + + + + +1. regedit.exe -> __HKEY\_CLASSES\_ROOT/Applications__ +2. Удалить лишнее \ No newline at end of file diff --git a/content/other/device-manuals/Cameron_URC-4020.jpg b/content/other/device-manuals/Cameron_URC-4020.jpg new file mode 100644 index 0000000..8d893eb Binary files /dev/null and b/content/other/device-manuals/Cameron_URC-4020.jpg differ diff --git a/content/other/device-manuals/Cameron_URC-4020.pdf b/content/other/device-manuals/Cameron_URC-4020.pdf new file mode 100644 index 0000000..296257a Binary files /dev/null and b/content/other/device-manuals/Cameron_URC-4020.pdf differ diff --git a/content/other/device-manuals/index.md b/content/other/device-manuals/index.md new file mode 100644 index 0000000..363d23c --- /dev/null +++ b/content/other/device-manuals/index.md @@ -0,0 +1,17 @@ +--- +title: "Инструкции от устройств" +categories: ["misc", "archive"] +date: 2020-08-19T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + +Отсканированные инструкции от различных устройств. + + + +### Универсальный пульт Maxmedia Сameron URC-4020 + +![Cameron_URC-4020](Cameron_URC-4020.jpg) + +[Cameron_URC-4020.pdf](Cameron_URC-4020.pdf) diff --git a/content/other/device-manuals/miniature.jpg b/content/other/device-manuals/miniature.jpg new file mode 100644 index 0000000..2ca134a Binary files /dev/null and b/content/other/device-manuals/miniature.jpg differ diff --git a/content/other/ic-dumps/16AT004_B.jpg b/content/other/ic-dumps/16AT004_B.jpg new file mode 100644 index 0000000..cb7249d Binary files /dev/null and b/content/other/ic-dumps/16AT004_B.jpg differ diff --git a/content/other/ic-dumps/16AT004_F.jpg b/content/other/ic-dumps/16AT004_F.jpg new file mode 100644 index 0000000..f1ab009 Binary files /dev/null and b/content/other/ic-dumps/16AT004_F.jpg differ diff --git a/content/other/ic-dumps/MX25L6405@Sunny_pnl_LC490DUY.zip b/content/other/ic-dumps/MX25L6405@Sunny_pnl_LC490DUY.zip new file mode 100644 index 0000000..9b814ec Binary files /dev/null and b/content/other/ic-dumps/MX25L6405@Sunny_pnl_LC490DUY.zip differ diff --git a/content/other/ic-dumps/bn41-01795a-25q40.zip b/content/other/ic-dumps/bn41-01795a-25q40.zip new file mode 100644 index 0000000..b841f0f Binary files /dev/null and b/content/other/ic-dumps/bn41-01795a-25q40.zip differ diff --git a/content/other/ic-dumps/index.md b/content/other/ic-dumps/index.md new file mode 100644 index 0000000..29989e2 --- /dev/null +++ b/content/other/ic-dumps/index.md @@ -0,0 +1,37 @@ +--- +title: "Дампы" +categories: ["misc", "archive"] +date: 2019-12-03T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Различные дампы микросхем энергонезависимой памяти, снятые с рабочей техники + + + +## Телевизоры + +### Samsung bn41-01795a + +Чип 25Q40 + +[bn41-01795a-25q40.zip](bn41-01795a-25q40.zip) + +### SUNNY SN049DLD + +Чип памяти 25Q64 + +Плата: + +![|300](16AT004_F.jpg) ![|300](16AT004_B.jpg) + +[MX25L6405@Sunny_pnl_LC490DUY.zip](MX25L6405@Sunny_pnl_LC490DUY.zip) + +Дамп взят [отсюда](https://www.amwajsat.net/showthread.php?t=5098). Успешно протестирован, язык французский. + +## BIOS + +... + diff --git a/content/other/ic-dumps/miniature.jpg b/content/other/ic-dumps/miniature.jpg new file mode 100644 index 0000000..18bc0ff Binary files /dev/null and b/content/other/ic-dumps/miniature.jpg differ diff --git a/content/other/logic-ic/4001.png b/content/other/logic-ic/4001.png new file mode 100644 index 0000000..c7bd3ee Binary files /dev/null and b/content/other/logic-ic/4001.png differ diff --git a/content/other/logic-ic/4001_s.png b/content/other/logic-ic/4001_s.png new file mode 100644 index 0000000..3b0e44b Binary files /dev/null and b/content/other/logic-ic/4001_s.png differ diff --git a/content/other/logic-ic/4001_single.png b/content/other/logic-ic/4001_single.png new file mode 100644 index 0000000..2f964a9 Binary files /dev/null and b/content/other/logic-ic/4001_single.png differ diff --git a/content/other/logic-ic/4049.png b/content/other/logic-ic/4049.png new file mode 100644 index 0000000..57cbf44 Binary files /dev/null and b/content/other/logic-ic/4049.png differ diff --git a/content/other/logic-ic/4049_s.png b/content/other/logic-ic/4049_s.png new file mode 100644 index 0000000..f1310b9 Binary files /dev/null and b/content/other/logic-ic/4049_s.png differ diff --git a/content/other/logic-ic/4049_single.png b/content/other/logic-ic/4049_single.png new file mode 100644 index 0000000..f944f4b Binary files /dev/null and b/content/other/logic-ic/4049_single.png differ diff --git a/content/other/logic-ic/4069.png b/content/other/logic-ic/4069.png new file mode 100644 index 0000000..b2fc54c Binary files /dev/null and b/content/other/logic-ic/4069.png differ diff --git a/content/other/logic-ic/4069_s.png b/content/other/logic-ic/4069_s.png new file mode 100644 index 0000000..de09e9f Binary files /dev/null and b/content/other/logic-ic/4069_s.png differ diff --git a/content/other/logic-ic/4069_single.png b/content/other/logic-ic/4069_single.png new file mode 100644 index 0000000..c690b39 Binary files /dev/null and b/content/other/logic-ic/4069_single.png differ diff --git a/content/other/logic-ic/4502.png b/content/other/logic-ic/4502.png new file mode 100644 index 0000000..950073f Binary files /dev/null and b/content/other/logic-ic/4502.png differ diff --git a/content/other/logic-ic/4502_s.png b/content/other/logic-ic/4502_s.png new file mode 100644 index 0000000..f4a2193 Binary files /dev/null and b/content/other/logic-ic/4502_s.png differ diff --git a/content/other/logic-ic/4502_single.png b/content/other/logic-ic/4502_single.png new file mode 100644 index 0000000..ffe1b6d Binary files /dev/null and b/content/other/logic-ic/4502_single.png differ diff --git a/content/other/logic-ic/and.png b/content/other/logic-ic/and.png new file mode 100644 index 0000000..0a9f488 Binary files /dev/null and b/content/other/logic-ic/and.png differ diff --git a/content/other/logic-ic/index.md b/content/other/logic-ic/index.md new file mode 100644 index 0000000..1aa145a --- /dev/null +++ b/content/other/logic-ic/index.md @@ -0,0 +1,190 @@ +--- +title: "Современные логические элементы" +categories: ["misc", "archive"] +date: 2016-06-30T00:00:00+03:00 +draft: true +featured_image: miniature.jpg +--- + + +Сборки логических элементов, которые можно найти практически в любом радиомагазине. + +> :warning: Статья не закончена. Когда-нибудь она будет доработана. + + +**Vss** - катод **(-)** + +**Vdd** - анод **(+)** + + + +

НЕ (NOT)

+ +

![nodeco:НЕ|](not.png)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
НазваниеОписаниеСтруктураРаспиновка
+

4069

+
6 логических элементов НЕ +

![|100](4069_s.png)

+

![|100](4069_single.png)

+
![|200](4069.png)
40496 логических элементов НЕ +

![|100](4049_s.png)

+

![|100](4049_single.png)

+
![|200](4049.png)
+

4502

+
6 логических элементов НЕ с блокировкой и запретом +

![|100](4502_s.png)

+

![|100](4502_single.png)

+
![|200](4502.png)
+ +

+ +

+ +

ИЛИ (OR)

+ +

![nodeco:ИЛИ|](or.png)

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
НазваниеОписаниеСтруктураРаспиновкаСхема ячейки
+

4069

+
6 логических элементов НЕ +

![|100](4069_s.png)

+

![|100](4049_single.png)

+
![|200](4069.png)
+ +

+ +

ИЛИ-НЕ (NOR)

+ +

![nodeco:ИЛИ-НЕ|](nor.png)

+ +

+ + + + + + + + + + + + + + + + + + + + + + +
НазваниеОписаниеСтруктураРаспиновка
+

4001

+
+

4 логических элемента ИЛИ-НЕ

+
![|100](4001_s.png) +

![|100](4001_single.png)

+
![|200](4001.png)
+ +

+ +

И (AND)

+ +

![nodeco:И|](and.png)

+ +

+ + + + + + + + + + + + + + + + + + + + + + +
НазваниеОписаниеСтруктураРаспиновка
+

4069

+
6 логических элементов НЕ![|100](4069_s.png) +

![|100](4049_single.png)

+
![|200](4069.png)
+ +

+ +

И-НЕ (NAND)

+ +

![nodeco:И-НЕ|](nand.png)

+ +

+ +| Название | Описание | Структура | Распиновка | +|----------|---------------------------|----------------------------------------------|-------------------| +| 4069 | 6 логических элементов НЕ | ![100](4069_s.png) ![100](4049_single.png) | ![|200](4069.png) | \ No newline at end of file diff --git a/content/other/logic-ic/miniature.jpg b/content/other/logic-ic/miniature.jpg new file mode 100644 index 0000000..a27ece0 Binary files /dev/null and b/content/other/logic-ic/miniature.jpg differ diff --git a/content/other/logic-ic/nand.png b/content/other/logic-ic/nand.png new file mode 100644 index 0000000..e108939 Binary files /dev/null and b/content/other/logic-ic/nand.png differ diff --git a/content/other/logic-ic/nor.png b/content/other/logic-ic/nor.png new file mode 100644 index 0000000..5f20278 Binary files /dev/null and b/content/other/logic-ic/nor.png differ diff --git a/content/other/logic-ic/not.png b/content/other/logic-ic/not.png new file mode 100644 index 0000000..9a4c835 Binary files /dev/null and b/content/other/logic-ic/not.png differ diff --git a/content/other/logic-ic/or.png b/content/other/logic-ic/or.png new file mode 100644 index 0000000..023815f Binary files /dev/null and b/content/other/logic-ic/or.png differ diff --git a/content/other/markdown-test/index.md b/content/other/markdown-test/index.md new file mode 100644 index 0000000..3c067d1 --- /dev/null +++ b/content/other/markdown-test/index.md @@ -0,0 +1,256 @@ +--- +title: "Markdown test" +date: 2022-12-24T14:16:25+03:00 +draft: false +categories: ["misc"] +--- + +Тут проверка + + + +--- +__Advertisement :)__ + +- __[pica](https://nodeca.github.io/pica/demo/)__ - high quality and fast image + resize in browser. +- __[babelfish](https://github.com/nodeca/babelfish/)__ - developer friendly + i18n with plurals support and easy syntax. + +You will like those projects! + +--- + +# h1 Heading 8-) +## h2 Heading +### h3 Heading +#### h4 Heading +##### h5 Heading +###### h6 Heading + + +## Horizontal Rules + +___ + +--- + +*** + + +## Typographic replacements + +Enable typographer option to see result. + +(c) (C) (r) (R) (tm) (TM) (p) (P) +- + +test.. test... test..... test?..... test!.... + +!!!!!! ???? ,, -- --- + +"Smartypants, double quotes" and 'single quotes' + + +## Emphasis + +**This is bold text** + +__This is bold text__ + +*This is italic text* + +_This is italic text_ + +~~Strikethrough~~ + + +## Blockquotes + + +> Blockquotes can also be nested... +>> ...by using additional greater-than signs right next to each other... +> > > ...or with spaces between arrows. + + +## Lists + +Unordered + ++ Create a list by starting a line with `+`, `-`, or `*` ++ Sub-lists are made by indenting 2 spaces: + - Marker character change forces new list start: + * Ac tristique libero volutpat at + + Facilisis in pretium nisl aliquet + - Nulla volutpat aliquam velit ++ Very easy! + +Ordered + +1. Lorem ipsum dolor sit amet +2. Consectetur adipiscing elit +3. Integer molestie lorem at massa + + +1. You can use sequential numbers... +1. ...or keep all the numbers as `1.` + +Start numbering with offset: + +57. foo +1. bar + + +## Code + +Inline `code` + +Indented code + + // Some comments + line 1 of code + line 2 of code + line 3 of code + + +Block code "fences" + +``` +Sample text here... +``` + +Syntax highlighting + +``` js +var foo = function (bar) { + return bar++; +}; + +console.log(foo(5)); +``` + +## Tables + +| Option | Description | +| ------ | ----------- | +| data | path to data files to supply the data that will be passed into templates. | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + +Right aligned columns + +| Option | Description | +| ------:| -----------:| +| data | path to data files to supply the data that will be passed into templates. | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + + +## Links + +[link text](http://dev.nodeca.com) + +[link with title](http://nodeca.github.io/pica/demo/ "title text!") + +Autoconverted link https://github.com/nodeca/pica (enable linkify to see) + + +## Images + +![Minion](https://octodex.github.com/images/minion.png) +![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") + +Like links, Images also have a footnote style syntax + +![Alt text][id] + +With a reference later in the document defining the URL location: + +[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat" + + +## Plugins + +The killer feature of `markdown-it` is very effective support of +[syntax plugins](https://www.npmjs.org/browse/keyword/markdown-it-plugin). + + +### [Emojies](https://github.com/markdown-it/markdown-it-emoji) + +> Classic markup: :wink: :crush: :cry: :tear: :laughing: :yum: +> +> Shortcuts (emoticons): :-) :-( 8-) ;) + +see [how to change output](https://github.com/markdown-it/markdown-it-emoji#change-output) with twemoji. + + +### [Subscript](https://github.com/markdown-it/markdown-it-sub) / [Superscript](https://github.com/markdown-it/markdown-it-sup) + +- 19^th^ +- H~2~O + + +### [\](https://github.com/markdown-it/markdown-it-ins) + +++Inserted text++ + + +### [\](https://github.com/markdown-it/markdown-it-mark) + +==Marked text== + + +### [Footnotes](https://github.com/markdown-it/markdown-it-footnote) + +Footnote 1 link[^first]. + +Footnote 2 link[^second]. + +Inline footnote^[Text of inline footnote] definition. + +Duplicated footnote reference[^second]. + +[^first]: Footnote **can have markup** + + and multiple paragraphs. + +[^second]: Footnote text. + + +### [Definition lists](https://github.com/markdown-it/markdown-it-deflist) + +Term 1 + +: Definition 1 +with lazy continuation. + +Term 2 with *inline markup* + +: Definition 2 + + { some code, part of Definition 2 } + + Third paragraph of definition 2. + +_Compact style:_ + +Term 1 + ~ Definition 1 + +Term 2 + ~ Definition 2a + ~ Definition 2b + + +### [Abbreviations](https://github.com/markdown-it/markdown-it-abbr) + +This is HTML abbreviation example. + +It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on. + +*[HTML]: Hyper Text Markup Language + +### [Custom containers](https://github.com/markdown-it/markdown-it-container) + +::: warning +*here be dragons* +::: diff --git a/content/other/mingw-libs/curl.7z b/content/other/mingw-libs/curl.7z new file mode 100644 index 0000000..253d6d5 Binary files /dev/null and b/content/other/mingw-libs/curl.7z differ diff --git a/content/other/mingw-libs/fltk.zip b/content/other/mingw-libs/fltk.zip new file mode 100644 index 0000000..a13b27d Binary files /dev/null and b/content/other/mingw-libs/fltk.zip differ diff --git a/content/other/mingw-libs/index.md b/content/other/mingw-libs/index.md new file mode 100644 index 0000000..b0f531c --- /dev/null +++ b/content/other/mingw-libs/index.md @@ -0,0 +1,37 @@ +--- +title: "Бибилотеки MinGW" +categories: ["cpp", "archive"] +date: 2016-02-19T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Тут находятся некоторые, уже откомпилированные мной, библиотеки для MinGW. + + + + +### PNG + +[png1621.7z](png1621.7z) + +### SSL + +[ssl.7z](ssl.7z) + +### FLTK + +[fltk.zip](fltk.zip) + +### Zlib + +[zlib128.7z](zlib128.7z) + +### Curl + +[curl.7z](curl.7z) + +### SQLite + +[sqlite.7z](sqlite.7z) \ No newline at end of file diff --git a/content/other/mingw-libs/miniature.jpg b/content/other/mingw-libs/miniature.jpg new file mode 100644 index 0000000..3cdc4e0 Binary files /dev/null and b/content/other/mingw-libs/miniature.jpg differ diff --git a/content/other/mingw-libs/png1621.7z b/content/other/mingw-libs/png1621.7z new file mode 100644 index 0000000..fed55cc Binary files /dev/null and b/content/other/mingw-libs/png1621.7z differ diff --git a/content/other/mingw-libs/sqlite.7z b/content/other/mingw-libs/sqlite.7z new file mode 100644 index 0000000..d42eb5b Binary files /dev/null and b/content/other/mingw-libs/sqlite.7z differ diff --git a/content/other/mingw-libs/ssl.7z b/content/other/mingw-libs/ssl.7z new file mode 100644 index 0000000..4658cf8 Binary files /dev/null and b/content/other/mingw-libs/ssl.7z differ diff --git a/content/other/mingw-libs/zlib128.7z b/content/other/mingw-libs/zlib128.7z new file mode 100644 index 0000000..ba5b989 Binary files /dev/null and b/content/other/mingw-libs/zlib128.7z differ diff --git a/content/other/pinouts/i2c_lcd_pinout.jpg b/content/other/pinouts/i2c_lcd_pinout.jpg new file mode 100644 index 0000000..3d92c88 Binary files /dev/null and b/content/other/pinouts/i2c_lcd_pinout.jpg differ diff --git a/content/other/pinouts/index.md b/content/other/pinouts/index.md new file mode 100644 index 0000000..7630e9f --- /dev/null +++ b/content/other/pinouts/index.md @@ -0,0 +1,21 @@ +--- +title: "Распиновки" +categories: ["misc", "archive"] +date: 2018-09-07T00:00:00+03:00 +draft: false +--- + + +Разнообразные найденные или выясненные распиновки + + + + +Распиновка модуля i2c - LCD + +i2c LCD adapter pinout + +(PCF8574T) + +![|547](i2c_lcd_pinout.jpg) + diff --git a/content/other/soft/ft232_2814.zip b/content/other/soft/ft232_2814.zip new file mode 100644 index 0000000..2dcb383 Binary files /dev/null and b/content/other/soft/ft232_2814.zip differ diff --git a/content/other/soft/ftdi.png b/content/other/soft/ftdi.png new file mode 100644 index 0000000..8d6e25f Binary files /dev/null and b/content/other/soft/ftdi.png differ diff --git a/content/other/soft/index.md b/content/other/soft/index.md new file mode 100644 index 0000000..0dd88b8 --- /dev/null +++ b/content/other/soft/index.md @@ -0,0 +1,33 @@ +--- +title: "Софт" +categories: ["misc", "archive"] +date: 2015-08-13T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Различный софт. + + + +--- + +### LCDPict + +![lcd](lcd.png) + +Редактор изображений и символов для LCD экранов + +[lcdpict.zip](lcdpict.zip) + +--- + +### Драйвер FTDI FT232 2.8.14 + +![ftdi](ftdi.png) + +Подходит для китайских копий FT232 + +[ft232_2814.zip](ft232_2814.zip) + diff --git a/content/other/soft/lcd.png b/content/other/soft/lcd.png new file mode 100644 index 0000000..407a150 Binary files /dev/null and b/content/other/soft/lcd.png differ diff --git a/content/other/soft/lcd_cloud.png b/content/other/soft/lcd_cloud.png new file mode 100644 index 0000000..1732c03 Binary files /dev/null and b/content/other/soft/lcd_cloud.png differ diff --git a/content/other/soft/lcdpict.png b/content/other/soft/lcdpict.png new file mode 100644 index 0000000..2bd9706 Binary files /dev/null and b/content/other/soft/lcdpict.png differ diff --git a/content/other/soft/lcdpict.zip b/content/other/soft/lcdpict.zip new file mode 100644 index 0000000..51bb0ac Binary files /dev/null and b/content/other/soft/lcdpict.zip differ diff --git a/content/other/soft/miniature.jpg b/content/other/soft/miniature.jpg new file mode 100644 index 0000000..d24bdde Binary files /dev/null and b/content/other/soft/miniature.jpg differ diff --git a/content/other/stm32f1x-makefile/index.md b/content/other/stm32f1x-makefile/index.md new file mode 100644 index 0000000..0350434 --- /dev/null +++ b/content/other/stm32f1x-makefile/index.md @@ -0,0 +1,217 @@ +--- +title: "Makefile для STM32F103" +categories: ["mcu", "archive"] +date: 2017-02-26T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Почти что в первый раз писал. Прошу простить за убогость и SPL. Всё это убирается. Под linux не проверялось. + + + +Рабочий проект: [stm32f103make.zip](stm32f103make.zip) + + +```makefile +CXX = arm-none-eabi-g++ +CC = arm-none-eabi-gcc +LD = arm-none-eabi-gcc +OBJCOPY = arm-none-eabi-objcopy +SIZE = arm-none-eabi-size +STFLASH = st-flash +OPENOCD = openocd +STUTIL = st-flash + + +OUTPUT_DIR = bin +OBJ_DIR = obj + +TARGET_NAME = led +TARGET_BINARY = $(TARGET_NAME).elf +TARGET_HEX = $(TARGET_NAME).hex + +vpath %.c ./src + +SOURCES = \ +main.c + +LDFLAGS_DEBUG = +CDFLAGS_DEBUG = -g3 -O0 + +LDFLAGS_RELEASE = +CDFLAGS_RELEASE = -O2 + +CFLAGS = -Wall \ +-mcpu=cortex-m3 \ +-mthumb \ +-D__HEAP_SIZE=0x0000 \ +-D__STACK_SIZE=0x0100 \ +-mfloat-abi=soft \ +-fno-strict-aliasing \ +-fdata-sections \ +-ffunction-sections \ +-DSTM32F103C8 \ +-DSTM32F10X_MD \ +-DUSE_STDPERIPH_DRIVER + +TARGET = $(OUTPUT_DIR)/$(TARGET_BINARY) + +LIBS = -lm + +LDFLAGS = \ +--specs=nosys.specs \ +--specs=nano.specs \ +-mcpu=cortex-m3 \ +-mthumb \ +-Wl,--defsym=__HEAP_SIZE=0x0000 \ +-Wl,--defsym=__STACK_SIZE=0x0100 \ +-mfloat-abi=soft \ +-fno-strict-aliasing \ +-fdata-sections \ +-ffunction-sections \ +-Wl,--gc-sections \ +-Wl,-script="./hardware/stm32f103c8_flash.ld" \ +-Wl,-Map=$(TARGET).map +#-u _printf_float + +INCLUDES = \ +-I. \ +-I./include \ +-I./hardware/include \ +-I./hardware/include/cmsis \ +-I./hardware/SPL/include + +STARUPFILE = hardware/src/startup_stm32f10x_md.S + +SOURCES_SPL = \ +stm32f10x_rcc.c \ +stm32f10x_gpio.c \ +stm32f10x_dma.c + +#stm32f10x_crc.c \ +#stm32f10x_flash.c \ +#stm32f10x_pwr.c \ +#stm32f10x_tim.c \ +#stm32f10x_adc.c \ +#stm32f10x_dac.c \ +#stm32f10x_fsmc.c \ +#stm32f10x_usart.c \ +#stm32f10x_bkp.c \ +#stm32f10x_dbgmcu.c \ +#stm32f10x_rtc.c \ +#stm32f10x_wwdg.c \ +#stm32f10x_can.c \ +#stm32f10x_i2c.c \ +#stm32f10x_sdio.c \ +#stm32f10x_cec.c \ +#stm32f10x_exti.c \ +#stm32f10x_iwdg.c \ +#stm32f10x_spi.c \ +#misc.c + +################################################################ + + +SOURCES += $(addprefix hardware/SPL/src/, $(SOURCES_SPL)) +SOURCES += hardware/src/system_stm32f10x.c + +HEX = $(OUTPUT_DIR)/$(TARGET_HEX) + +STARTUPOBJ = $(notdir $(STARUPFILE)) +STARTUPOBJ := $(patsubst %.S, $(OBJ_DIR)/%.S.o, $(STARTUPOBJ)) + +OBJECTS = $(patsubst %, $(OBJ_DIR)/%.o, $(SOURCES)) +OBJECTS += $(STARTUPOBJ) + +DEPS = $(OBJECTS:.o=.d) + + + +all: release + +release: LDFLAGS+=$(LDFLAGS_RELEASE) +release: CFLAGS+=$(CDFLAGS_RELEASE) +release: _firmware + +debug: LDFLAGS+=$(LDFLAGS_DEBUG) +debug: CFLAGS+=$(CDFLAGS_DEBUG) +debug: _firmware + + +_firmware: $(TARGET) $(HEX) + + +$(TARGET): $(OBJECTS) | $(OUTPUT_DIR) $(OBJ_DIR) + $(LD) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS) + $(SIZE) --format=berkeley $(TARGET) + +obj/%.cpp.o: %.cpp +ifeq ($(OS), Windows_NT) + $(eval dirname=$(subst /,\\,$(dir $@))) + @ if NOT EXIST $(dirname) mkdir $(dirname) +else + @mkdir -p $(dir $@) $(TO_NULL) +endif + $(CXX) -c -MMD -MP $(CFLAGS) $(INCLUDES) $< -o $@ + +obj/%.c.o: %.c +ifeq ($(OS), Windows_NT) + $(eval dirname=$(subst /,\\,$(dir $@))) + @ if NOT EXIST $(dirname) mkdir $(dirname) +else + @mkdir -p $(dir $@) $(TO_NULL) +endif + $(CC) -c -MMD -MP $(CFLAGS) $(INCLUDES) $< -o $@ + +$(STARTUPOBJ): + $(CC) -c -MMD -MP $(CFLAGS) $(INCLUDES) $(STARUPFILE) -o $(STARTUPOBJ) + +$(HEX): $(TARGET) + $(OBJCOPY) -O ihex $(TARGET) $(HEX) + +$(OUTPUT_DIR): + @mkdir $(OUTPUT_DIR) + +$(OBJ_DIR): + @mkdir $(OBJ_DIR) + +_size: $(TARGET) + $(SIZE) --format=berkeley $(TARGET) + + +flash: flash-ocd + +flash-stutil: + $(STFLASH) --format ihex write $(HEX) + +flash-ocd: + $(OPENOCD) -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program $(TARGET) verify reset exit" + +srclist: + @echo $(SOURCES) + +objlist: + @echo $(OBJECTS) + +clean: + +ifeq ($(OS), Windows_NT) + -del $(subst /,\\,$(OBJECTS)) + -del $(subst /,\\,$(DEPS)) + -rmdir /S /Q $(OBJ_DIR) + -del /Q /F $(OUTPUT_DIR)\\$(TARGET_BINARY) + -del /Q /F $(OUTPUT_DIR)\\$(TARGET_BINARY).map + -del /Q /F $(OUTPUT_DIR)\\$(TARGET_HEX) +else + -rm -f $(OBJECTS) + -rm -f $(DEPS) + -rm -rf $(OBJ_DIR) + -rm -f $(OUTPUT_DIR)/$(TARGET_BINARY) + -rm -f $(OUTPUT_DIR)/$(TARGET_BINARY).map + -rm -f $(OUTPUT_DIR)/$(TARGET_HEX) +endif + +-include $(DEPS) +``` diff --git a/content/other/stm32f1x-makefile/miniature.jpg b/content/other/stm32f1x-makefile/miniature.jpg new file mode 100644 index 0000000..87773de Binary files /dev/null and b/content/other/stm32f1x-makefile/miniature.jpg differ diff --git a/content/other/stm32f1x-makefile/stm32f103make.zip b/content/other/stm32f1x-makefile/stm32f103make.zip new file mode 100644 index 0000000..8e88def Binary files /dev/null and b/content/other/stm32f1x-makefile/stm32f103make.zip differ diff --git a/content/other/thanks/index.md b/content/other/thanks/index.md new file mode 100644 index 0000000..508e61f --- /dev/null +++ b/content/other/thanks/index.md @@ -0,0 +1,18 @@ +--- +title: "Спасибы" +categories: ["misc", "pinned"] +date: 2016-05-14T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + +Нечеловеческое спасибо за всё следующим людям: + +* Иван Истомин ([Istom1n](https://vk.com/id9920588)) +* Кирилл Иванов +* Игорь Окунский ([Clarity](https://vk.com/sundayclarity)) +* Игорь Водка ([Uhehesh](https://vk.com/id171249225)) +* Дмитрий Тычинин ([iMityan](https://vk.com/id88536880)) +* Даня Соломыкин ([CrazyClown](https://vk.com/id23105063)) +* Алексей Шалпегин (15432) +* Валерия ([Mithriss](https://vk.com/id244743608)) diff --git a/content/other/thanks/miniature.jpg b/content/other/thanks/miniature.jpg new file mode 100644 index 0000000..c035e61 Binary files /dev/null and b/content/other/thanks/miniature.jpg differ diff --git a/content/posts/avr-freq-meter/3d1.png b/content/posts/avr-freq-meter/3d1.png new file mode 100644 index 0000000..f9faa05 Binary files /dev/null and b/content/posts/avr-freq-meter/3d1.png differ diff --git a/content/posts/avr-freq-meter/7seg-freq-corel.zip b/content/posts/avr-freq-meter/7seg-freq-corel.zip new file mode 100644 index 0000000..1f51fe6 Binary files /dev/null and b/content/posts/avr-freq-meter/7seg-freq-corel.zip differ diff --git a/content/posts/avr-freq-meter/avr-7seg-freq-curse.docx b/content/posts/avr-freq-meter/avr-7seg-freq-curse.docx new file mode 100644 index 0000000..d027160 Binary files /dev/null and b/content/posts/avr-freq-meter/avr-7seg-freq-curse.docx differ diff --git a/content/posts/avr-freq-meter/compas1.png b/content/posts/avr-freq-meter/compas1.png new file mode 100644 index 0000000..784cf7a Binary files /dev/null and b/content/posts/avr-freq-meter/compas1.png differ diff --git a/content/posts/avr-freq-meter/compas2.png b/content/posts/avr-freq-meter/compas2.png new file mode 100644 index 0000000..a502f21 Binary files /dev/null and b/content/posts/avr-freq-meter/compas2.png differ diff --git a/content/posts/avr-freq-meter/compas3.png b/content/posts/avr-freq-meter/compas3.png new file mode 100644 index 0000000..8ebb256 Binary files /dev/null and b/content/posts/avr-freq-meter/compas3.png differ diff --git a/content/posts/avr-freq-meter/draft.png b/content/posts/avr-freq-meter/draft.png new file mode 100644 index 0000000..0f470ee Binary files /dev/null and b/content/posts/avr-freq-meter/draft.png differ diff --git a/content/posts/avr-freq-meter/freq-meter-KOMPAS.zip b/content/posts/avr-freq-meter/freq-meter-KOMPAS.zip new file mode 100644 index 0000000..4df5adb Binary files /dev/null and b/content/posts/avr-freq-meter/freq-meter-KOMPAS.zip differ diff --git a/content/posts/avr-freq-meter/freq_sch.png b/content/posts/avr-freq-meter/freq_sch.png new file mode 100644 index 0000000..83c32e8 Binary files /dev/null and b/content/posts/avr-freq-meter/freq_sch.png differ diff --git a/content/posts/avr-freq-meter/index.md b/content/posts/avr-freq-meter/index.md new file mode 100644 index 0000000..2eaea3e --- /dev/null +++ b/content/posts/avr-freq-meter/index.md @@ -0,0 +1,239 @@ +--- +title: "Простой частотомер на AVR - курсовая работа" +categories: ["mcu", "archive"] +date: 2015-08-16T00:00:00+03:00 +draft: true +featured_image: miniature.jpg +--- + + +Итак, пришло время время делать курсовые работы. Мне попалась тема "Частотомер с передачей данных по последовательному порту и динамической индикацией". Значит, будем использовать таймер, внешние прерывания и динамическую индикацию. Использовал семисегментный индикатор с четырьмя разрядами и общим анодом. Микроконтроллер выберем Atmega16. Именно с ним я не чувствовал дефицита ножек. Приступим. + + + +> :warning: Этот текст – древний стыд. Не нужно принимать его всерьёз. Сейчас бы такой бред не сделал. + +Работа заключается в следующем: нужно спроектировать схему устройства, развести печатку, а также изготовить корпус для готового устройства. В КОМПАС 3D, разумеется. + +Для начала нам нужно определиться как именно считать частоту. Я решил использовать таймер, тактированный часовым кварцем и засекать количество внешних прерываний за секунду. Прерывания использовал по нарастающему фронту. Возможно, я не прав, но, во благо, на железе собирать ничего не требуется. + +Делаем всё в протеусе. Схема получилась такая: + +![Схема|786](freq_sch.png) + +Пишем программу. Микроконтроллер должен считать импульсы в секунду и выводить их на семисегментный индикатор. А также отдавать данные по UART. + +main.h: +```c +#ifndef __MAIN_H_ +#define __MAIN_H_ + +#include +#include + +typedef uint8_t byte; + +byte buf[16]; + +uint32_t freq; +uint32_t freq_max; +uint32_t measure_buf; + +// порт для сегментов +#define SEGMENTS_DDR DDRA +#define SEGMENTS_PORT PORTA + + +// порт для разрядов +#define DIGITS_DDR DDRC +#define DIGITS_PORT PORTC + + +#define SWITCH_TIME 45 // время между переключениями разрядов; чем меньше, тем меньше мерцает + +#define INPUT 0x00 +#define OUTPUT 0xFF + + +#define SYMBOLS_SIZE 11 // количество символов в таблице +byte symbols[SYMBOLS_SIZE] = //состояния пинов для символов + { + 0b00111111, // 0 + 0b00000110, // 1 + 0b01011011, // 2 + 0b01001111, // 3 + 0b01100110, // 4 + 0b01101101, // 5 + 0b01111101, // 6 + 0b00000111, // 7 + 0b01111111, // 8 + 0b01101111, // 9 + 0b10000000 // . + }; + +int main(void); + +void switchDigit(byte digit); // показать нужный разряд, остальные погасить; значения от 0 до 3 +void showDigit(byte number, bool dot); // вывести символ на разряд, с точкой или без; значения от 0 до SYMBOLS_SIZE +void initTimer(); // инициализация таймера (для нас - часового) +void initInterrupts(); //инициализация прерываний +void initUART(); //инициализация последовательного порта +void sendByte(byte b); //отправка байта по UART +void sendString(byte *str); //отправка строки по UART + +#endif //__MAIN_H_ +``` + +main.c: +```c +#include "main.h" +#include +#include +#include +#include + + +int main(void) { + SEGMENTS_DDR = OUTPUT; // настраиваем порты ввода-вывода + DIGITS_DDR = OUTPUT; + DIGITS_PORT = 0xFF; + + initTimer(); + initInterrupts(); + initUART(); + + byte i; + uint32_t num; + + sprintf(buf, "? Stabilization...\r\n"); + sendString(buf); + _delay_ms(100); // ожидаем стабилизации таймера + sprintf(buf, "? Init finished!\r\n"); + sendString(buf); + + while (1) { + + num = freq > 9999 ? 9999 : freq; + + for (i = 0; i < 4; ++i) { // перебираем все разряды, разбираем частоту на цифры + switchDigit(i); + switch (i) { + case 0: + showDigit((byte) ((num / 1000) % 10), false); + break; + case 1: + showDigit((byte) ((num / 100) % 10), false); + break; + case 2: + showDigit((byte) ((num / 10) % 10), false); + break; + case 3: + showDigit(num % 10, false); + break; + + default: + break; + } + _delay_ms(SWITCH_TIME); + } + + } +} + +ISR(TIMER2_OVF_vect) { // прерывание таймера при переполнении + freq = measure_buf; + if( freq > freq_max) freq_max = freq; + measure_buf = 0; + + + sprintf(buf, "> Freq: %dHz, ", freq); // отправляем данные + sendString(buf); + sprintf(buf, "Max: %dHz\r\n", freq_max); + sendString(buf); + + +} + +ISR(INT0_vect) { //внешнее прерывание + measure_buf++; +} + +void showDigit(byte digit, bool dot) { + SEGMENTS_PORT = ~symbols[digit > SYMBOLS_SIZE - 1 ? 10 : digit] | (dot ? symbols[10] : 0); +} + +void switchDigit(byte number) { + DIGITS_PORT = number < 4 ? (byte) (1 << number) : 0x00; +} + +void initTimer() { + ASSR |= _BV(AS2); // асинхронный режим, тактируемся от часового кварца + TCCR2 = _BV(CS20) | _BV(CS22); //предделитель 128, одна секунда + TIMSK |= _BV(TOIE2); // включаем таймер +} + +void initInterrupts() { + MCUCR = (1 << ISC01) | (1 << ISC00); //прерывание по растущему форонту + GICR = (1 << INT0); //включаем прерывание на INT0 + sei(); // разрешаем прерывания +} + +void initUART() { + // выставляем скорость: 9600 при частоте 8МГц + // UBRR=8000000/(16*9600)-1=51.0833, округляем = 51 (0x33) + UBRRH = 0x00; + UBRRL = 0x33; + + // Разрешаем приём и передачу + UCSRB = (1 << RXEN) | (1 << TXEN); + UCSRB |= (1 << RXCIE); + + // устанавливаем формат: 8 бит данных, 2 стоп бита + UCSRC = (1 << URSEL) | (1 << USBS) | (3 << UCSZ0); +} + +void sendByte(byte b) { + while ( !(UCSRA & (1< + + +Например, мы хотим включить ножку 5 порта C. В CVAvr это делается так: + +```c +PORTC.5 = 1; +``` + +А в WinAvr (avr-gcc) это делается так (что более правильно, я не спорю, но менее комфортно): + +```c +PORTC |= _BV(5); +``` + +И выключаем ту же ножку. CVAvr: + +```c +PORTC.5 = 0; +``` + +А в WinAvr: + +```c +PORTC &= ~_BV(5); +``` + +Не так наглядно, согласитесь? Так что попробуем добиться такого же вида обращения к портам как и в CVAvr. + +Для этого нужно создать восьмибитную структуру: + +```c +struct port_byte { + bool P0 : 1; + bool P1 : 1; + bool P2 : 1; + bool P3 : 1; + bool P4 : 1; + bool P5 : 1; + bool P6 : 1; + bool P7 : 1; +}; +``` + +Дабы компилятор не ругался на bool нужно подключить заголовок stdbool.h + +Теперь самое интересное. Нужно создать переменную-указатель для нужного порта и присвоить ей начальный адрес. В данном случае используем PORTC: + +```c +struct port_byte *CVPORTC = (struct port_byte *) &(PORTC); +``` + +Готово! Теперь можно обращаться к ножкам порта через эту переменную: + +```c +CVPORTC->P5 = 1; +_delay_ms(500); +CVPORTC->P5 = 0; +``` diff --git a/content/posts/avr-gcc-cvports/miniature.jpg b/content/posts/avr-gcc-cvports/miniature.jpg new file mode 100644 index 0000000..54eeb5d Binary files /dev/null and b/content/posts/avr-gcc-cvports/miniature.jpg differ diff --git a/content/posts/avr-lcd-images/index.md b/content/posts/avr-lcd-images/index.md new file mode 100644 index 0000000..09b1ae5 --- /dev/null +++ b/content/posts/avr-lcd-images/index.md @@ -0,0 +1,91 @@ +--- +title: "Вывод иконок на дисплей Nokia 3310/5110 (переходим на avr-gcc)" +categories: ["mcu", "archive"] +date: 2015-08-13T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Наконец-то переехал с CVAvr на AVR-GCC. От нечего делать начал собирать барометр. Купил nokia3310, выдрал дисплей. Библиотеку использовал [вот эту](https://github.com/gresolio/N3310Lib). Всё отлично, но библиотека умеет рисовать круги, линии, прямоугольники, выводить полноэкранные изображения, НО. Что должен уметь электронный барометр? + + + +Правильно, определять погоду по давлению. И выводить картинку с облачком или солнышком. А с полноэкранным изображением это делать не вариант - занимает кучу памяти да и с обновлением дисплея будет беда. Так что, я взялся за дело. Просидев весь вечер, написал программку-рисовалку картинок с конвертацией в массив и функцию-дополнение к библиотеке. Вот так выглядит программа: + +![LCDPict|](lcdpict.png) + +Прямая ссылка, по традиции, в конце статьи. + +Функция выглядит следующим образом: + +```c +byte LCDIcon(const byte *pic, byte x, byte y, byte arrayRows, byte arrayColumns, byte progMem) { + byte iterCol; + byte iterRow; + byte iterByte; + byte picX = x; + byte picY = y; + byte symbolChar; + + for (iterCol = 0; iterCol < arrayColumns; iterCol++) { + for (iterRow = 0; iterRow < arrayRows; iterRow++) { + if (progMem) { + symbolChar = (byte) pgm_read_byte(&pic[iterCol + iterRow * arrayColumns]); + } else { + symbolChar = pic[iterCol + iterRow * arrayColumns]; + } + for (iterByte = 0; iterByte < 8; iterByte++) { + if ((symbolChar >> iterByte) & 1) { + LcdPixel(picX, picY, PIXEL_ON); + } + picY++; + } + } + picY = y; + picX++; + } + + UpdateLcd = TRUE; + return OK; +} +``` + +В качестве первого аргумента скармливаем **указатель на первый элемент массива**, второй и третий - координаты картинки,предпоследние аргументы - размер **массива, не картинки**. Не путать. Последний аргумент определяет откуда читать данные: из памяти МК (атрибут **PROGMEM**) или же из оперативной памяти. Пример: + +```c +#include +#include +#include +#include "n3310.h" + + +const byte out[2][24] = { + {0x0, 0x0, 0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0, 0xc, 0x6, 0x86, 0xc6, 0xec, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x0, 0x0, 0x0, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x0, 0x18, 0x10, 0x10, 0x10, 0x19, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0} +}; + +int main(void) { + + LcdInit(); + + while (1) { + LcdClear(); + LCDIcon(&out[0][0], 0, 0, 2, 24, false); + LcdUpdate(); + _delay_ms(5000); + } + +} +``` + +UPD: Только сейчас заметил, что в программе неверно написан тип данных. Вместо **const char out** нужно использовать **const unsigned char out.** Исходник я давно потерял, поэтому исправить не могу. + + +**Ссылки:** + +[LCDPict](lcdpict.zip) + +[Библиотека для дисплея nokia3310](https://github.com/gresolio/N3310Lib) + +[Форк библиотеки с программным SPI](https://github.com/MultiMote/N3310Lib) \ No newline at end of file diff --git a/content/posts/avr-lcd-images/lcdpict.png b/content/posts/avr-lcd-images/lcdpict.png new file mode 100644 index 0000000..2bd9706 Binary files /dev/null and b/content/posts/avr-lcd-images/lcdpict.png differ diff --git a/content/posts/avr-lcd-images/lcdpict.zip b/content/posts/avr-lcd-images/lcdpict.zip new file mode 100644 index 0000000..51bb0ac Binary files /dev/null and b/content/posts/avr-lcd-images/lcdpict.zip differ diff --git a/content/posts/avr-lcd-images/miniature.jpg b/content/posts/avr-lcd-images/miniature.jpg new file mode 100644 index 0000000..1fe4b07 Binary files /dev/null and b/content/posts/avr-lcd-images/miniature.jpg differ diff --git a/content/posts/avr-siemens-lcd/PCF8812.pdf b/content/posts/avr-siemens-lcd/PCF8812.pdf new file mode 100644 index 0000000..b6d3a96 Binary files /dev/null and b/content/posts/avr-siemens-lcd/PCF8812.pdf differ diff --git a/content/posts/avr-siemens-lcd/helloworld.jpg b/content/posts/avr-siemens-lcd/helloworld.jpg new file mode 100644 index 0000000..4d487a3 Binary files /dev/null and b/content/posts/avr-siemens-lcd/helloworld.jpg differ diff --git a/content/posts/avr-siemens-lcd/index.md b/content/posts/avr-siemens-lcd/index.md new file mode 100644 index 0000000..6a96e42 --- /dev/null +++ b/content/posts/avr-siemens-lcd/index.md @@ -0,0 +1,1202 @@ +--- +title: "Подключение дисплея от Siemens C55/A55/A52 к AVR" +categories: ["mcu", "archive"] +date: 2016-02-19T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Вот на днях решил порыться в своих запасах запчастей от мобильных телефонах. И заметил дисплей с маркировкой LPH8694-3. Погуглив, я выяснил что это дисплей от телефонов Siemens C55/A55/A52. Ну что ж добру пропадать, будем подключать. + + + +> :hint: Статья не закончена. +> Когда-нибудь она будет доработана. + +![Маркировка экрана|400](lcd.jpg) + +Экран имеет весьма странное разрешение экрана – 101 на 64 точки (в [даташите](PCF8812.pdf) вообще написано, что 102x64). Это намного больше, чем у дисплея, которым я обычно пользуюсь (у nokia 5110 – 64 на 48 точек). + +За основу я решил использовать [библиотеку](https://github.com/gresolio/N3310Lib) уважаемого товарища [gresolio](https://github.com/gresolio). Дисплеи очень похожи, но немного отличается инициализация. Да и доработать библиотеку под новое разрешение экрана тоже нужно. + +![Распиновка дисплея (вид со стороны контактов)|338](lph8684.png) + +Главное отличие в инициализации, без чего дисплей не запустится вообще – способ питания. + +Нужно найти вот эту строку в **LcdInit**: + +``` c +LcdSend( 0x13, LCD_CMD ); // Настройка питания (LCD bias mode 1:48) +``` + +И заменить на: + +```c +LcdSend( 0x16, LCD_CMD ); +``` + +**LcdGotoXYFont**, до: + +```c +byte LcdGotoXYFont ( byte x, byte y ) +{ + // Проверка границ + if( x > 13 || y > 5 ) return OUT_OF_BORDER; + + // Вычисление указателя. Определен как адрес в пределах 504 байт + LcdCacheIdx = x * 6 + y * 84; + return OK; +} +``` + +После: + +```c +byte LcdGotoXYFont ( byte x, byte y ) +{ + // Проверка границ + if( x > LCD_COLS || y > LCD_LINES ) return OUT_OF_BORDER; + + // Вычисление указателя. Определен как адрес в пределах 504 байт + LcdCacheIdx = x * LCD_LINES + y * LCD_X_RES; + return OK; +} +``` + +**LcdChr**, до: + +```c +else if ( size == FONT_2X ) +{ + tmpIdx = LcdCacheIdx - 84; +``` + +После: + +```c +else if ( size == FONT_2X ) +{ + tmpIdx = LcdCacheIdx - LCD_X_RES; +``` + +До: + +```c +// Копируем две части в кэш +LcdCache[tmpIdx++] = b1; +LcdCache[tmpIdx++] = b1; +LcdCache[tmpIdx + 82] = b2; +LcdCache[tmpIdx + 83] = b2; +``` + +После: + +```c +LcdCache[tmpIdx++] = b1; +LcdCache[tmpIdx++] = b1; +LcdCache[tmpIdx + LCD_X_RES - 2] = b2; +LcdCache[tmpIdx + LCD_X_RES - 1] = b2; +``` + +**LcdPixel**, до: + +```c +// Пересчет индекса и смещения +index = ( ( y / 8 ) * 84 ) + x; +offset = y - ( ( y / 8 ) * 8 ); +``` + +После + +```c +// Пересчет индекса и смещения +index = ( ( y / LCD_LINES ) * LCD_X_RES ) + x; +offset = y - ( ( y / 8) * LCD_LINES ); +``` + + +**n3310.h**, до: + +```c +// Разрешение дисплея в пикселях +#define LCD_X_RES 84 // разрешение по горизонтали +#define LCD_Y_RES 48 // разрешение по вертикали +``` + +После: + +```c +// Разрешение дисплея в пикселях +#define LCD_X_RES 102 // разрешение по горизонтали +#define LCD_Y_RES 65 // разрешение по вертикали +#define LCD_LINES (LCD_Y_RES / 8) // количество строк +#define LCD_COLS (LCD_X_RES / 5) // количество столбцов +``` + +Возможно, это не всё. + +Вот то, что получилось: + +sc55.h: +```c +/* + * Имя : n3310.h + * + * Описание : Это заголовочный файл для драйвера графического LCD от Nokia 3310, а также его китайских клонов. + * Базируется на коде библиотек написанных Sylvain Bissonnette и Fandi Gunawan: + * http://www.microsyl.com/index.php/2010/03/24/nokia-lcd-library/ + * http://fandigunawan.wordpress.com/2008/06/18/lcd-nokia-3310-pcd8544-driver-in-winavravr-gcc/ + * Основные отличия между оригиналом и клоном хорошо описаны в статье от Aheir: + * http://radiokot.ru/articles/29/ + * + * Автор : Xander Gresolio + * Веб-страница : http://we.easyelectronics.ru/profile/XANDER/ + * + * Лицензия : GPL v3.0 + * + * Компилятор : WinAVR, GCC for AVR platform + */ + +#ifndef _SC55_H_ +#define _SC55_H_ + +#include + +// Порт к которому подключен LCD (здесь пример распиновки для ATmega8) +#define LCD_PORT PORTB +#define LCD_DDR DDRB + +// Распиновка порта +#define LCD_DC_PIN PB1 +#define LCD_CE_PIN PB2 +#define LCD_DATA_PIN PB3 +#define LCD_RST_PIN PB4 +#define LCD_CLK_PIN PB5 + +// Разрешение дисплея в пикселях +#define LCD_X_RES 102 // разрешение по горизонтали +#define LCD_Y_RES 65 // разрешение по вертикали +#define LCD_LINES (LCD_Y_RES / 8) // количество строк +#define LCD_COLS (LCD_X_RES / 5) // количество столбцов + +// Настройки для рисования группы прямоугольников функцией LcdBars ( byte data[], byte numbBars, byte width, byte multiplier ) +#define EMPTY_SPACE_BARS 2 // расстояние между прямоугольниками +#define BAR_X 30 // координата x +#define BAR_Y 47 // координата y + +// Размер кэша ( 84 * 48 ) / 8 = 504 байта +#define LCD_CACHE_SIZE ( ( LCD_X_RES * LCD_Y_RES ) / 8 ) + +#define FALSE 0 +#define TRUE 1 + +// Для возвращаемых значений +#define OK 0 // Безошибочная отрисовка +#define OUT_OF_BORDER 1 // Выход за границы дисплея +#define OK_WITH_WRAP 2 // Переход на начало (ситуация автоинкремента указателя курсора при выводе длинного текста) + +typedef unsigned char byte; + +// Перечисления +typedef enum +{ + LCD_CMD = 0, // Команда + LCD_DATA = 1 // Данные + +} LcdCmdData; + +typedef enum +{ + PIXEL_OFF = 0, // Погасить пиксели дисплея + PIXEL_ON = 1, // Включить пиксели дисплея + PIXEL_XOR = 2 // Инвертировать пиксели + +} LcdPixelMode; + +typedef enum +{ + FONT_1X = 1, // Обычный размер шрифта 5x7 + FONT_2X = 2 // Увеличенный размер шрифта + +} LcdFontSize; + +// Прототипы функций, детальную информацию смотрим внутри n3310lcd.c +void LcdInit ( void ); // Инициализация +void LcdClear ( void ); // Очистка буфера +void LcdUpdate ( void ); // Копирование буфера в ОЗУ дисплея +void LcdImage ( const byte *imageData ); // Рисование картинки из массива в Flash ROM +void LcdContrast ( byte contrast ); // Установка контрастности дисплея +byte LcdGotoXYFont ( byte x, byte y ); // Установка курсора в позицию x,y +byte LcdChr ( LcdFontSize size, byte ch ); // Вывод символа в текущей позиции +byte LcdStr ( LcdFontSize size, byte dataArray[] ); // Вывод строки сохраненной в RAM +byte LcdFStr ( LcdFontSize size, const byte *dataPtr ); // Вывод строки сохраненной в Flash ROM +byte LcdPixel ( byte x, byte y, LcdPixelMode mode ); // Точка +byte LcdLine ( byte x1, byte y1, byte x2, byte y2, LcdPixelMode mode ); // Линия +byte LcdCircle ( byte x, byte y, byte radius, LcdPixelMode mode); // Окружность +byte LcdRect ( byte x1, byte y1, byte x2, byte y2, LcdPixelMode mode ); // Прямоугольник +byte LcdSingleBar ( byte baseX, byte baseY, byte height, byte width, LcdPixelMode mode ); // Один +byte LcdBars ( byte data[], byte numbBars, byte width, byte multiplier ); // Несколько + + + +/* + * Таблица для отображения символов (ASCII[0x20-0x7F] + CP1251[0xC0-0xFF] = всего 160 символов) + */ +static const byte FontLookup [][5] PROGMEM= +{ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x20 32 + { 0x00, 0x00, 0x5F, 0x00, 0x00 }, // ! 0x21 33 + { 0x00, 0x07, 0x00, 0x07, 0x00 }, // " 0x22 34 + { 0x14, 0x7F, 0x14, 0x7F, 0x14 }, // # 0x23 35 + { 0x24, 0x2A, 0x7F, 0x2A, 0x12 }, // $ 0x24 36 + { 0x4C, 0x2C, 0x10, 0x68, 0x64 }, // % 0x25 37 + { 0x36, 0x49, 0x55, 0x22, 0x50 }, // & 0x26 38 + { 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' 0x27 39 + { 0x00, 0x1C, 0x22, 0x41, 0x00 }, // ( 0x28 40 + { 0x00, 0x41, 0x22, 0x1C, 0x00 }, // ) 0x29 41 + { 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * 0x2A 42 + { 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + 0x2B 43 + { 0x00, 0x00, 0x50, 0x30, 0x00 }, // , 0x2C 44 + { 0x10, 0x10, 0x10, 0x10, 0x10 }, // - 0x2D 45 + { 0x00, 0x60, 0x60, 0x00, 0x00 }, // . 0x2E 46 + { 0x20, 0x10, 0x08, 0x04, 0x02 }, // / 0x2F 47 + { 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 0x30 48 + { 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 0x31 49 + { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 0x32 50 + { 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 0x33 51 + { 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 0x34 52 + { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 0x35 53 + { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 0x36 54 + { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 0x37 55 + { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 0x38 56 + { 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 0x39 57 + { 0x00, 0x36, 0x36, 0x00, 0x00 }, // : 0x3A 58 + { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; 0x3B 59 + { 0x08, 0x14, 0x22, 0x41, 0x00 }, // < 0x3C 60 + { 0x14, 0x14, 0x14, 0x14, 0x14 }, // = 0x3D 61 + { 0x00, 0x41, 0x22, 0x14, 0x08 }, // > 0x3E 62 + { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? 0x3F 63 + { 0x32, 0x49, 0x79, 0x41, 0x3E }, // @ 0x40 64 + { 0x7E, 0x11, 0x11, 0x11, 0x7E }, // A 0x41 65 + { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B 0x42 66 + { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C 0x43 67 + { 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D 0x44 68 + { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E 0x45 69 + { 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F 0x46 70 + { 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G 0x47 71 + { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H 0x48 72 + { 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I 0x49 73 + { 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J 0x4A 74 + { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K 0x4B 75 + { 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L 0x4C 76 + { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M 0x4D 77 + { 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N 0x4E 78 + { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O 0x4F 79 + { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P 0x50 80 + { 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q 0x51 81 + { 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R 0x52 82 + { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S 0x53 83 + { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T 0x54 84 + { 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U 0x55 85 + { 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V 0x56 86 + { 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W 0x57 87 + { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X 0x58 88 + { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y 0x59 89 + { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z 0x5A 90 + { 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ 0x5B 91 + { 0x02, 0x04, 0x08, 0x10, 0x20 }, // \ 0x5C 92 + { 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] 0x5D 93 + { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ 0x5E 94 + { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ 0x5F 95 + { 0x00, 0x01, 0x02, 0x04, 0x00 }, // ` 0x60 96 + { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a 0x61 97 + { 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b 0x62 98 + { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c 0x63 99 + { 0x38, 0x44, 0x44, 0x48, 0x7F }, // d 0x64 100 + { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e 0x65 101 + { 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f 0x66 102 + { 0x0C, 0x52, 0x52, 0x52, 0x3E }, // g 0x67 103 + { 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h 0x68 104 + { 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i 0x69 105 + { 0x20, 0x40, 0x44, 0x3D, 0x00 }, // j 0x6A 106 + { 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k 0x6B 107 + { 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l 0x6C 108 + { 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m 0x6D 109 + { 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n 0x6E 110 + { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o 0x6F 111 + { 0x7C, 0x14, 0x14, 0x14, 0x08 }, // p 0x70 112 + { 0x08, 0x14, 0x14, 0x18, 0x7C }, // q 0x71 113 + { 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r 0x72 114 + { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s 0x73 115 + { 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t 0x74 116 + { 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u 0x75 117 + { 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v 0x76 118 + { 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w 0x77 119 + { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x 0x78 120 + { 0x0C, 0x50, 0x50, 0x50, 0x3C }, // y 0x79 121 + { 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z 0x7A 122 + { 0x00, 0x08, 0x36, 0x41, 0x00 }, // { 0x7B 123 + { 0x00, 0x00, 0x7F, 0x00, 0x00 }, // | 0x7C 124 + { 0x00, 0x41, 0x36, 0x08, 0x00 }, // } 0x7D 125 + { 0x08, 0x04, 0x08, 0x10, 0x08 }, // ~ 0x7E 126 + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, //  0x7F 127 + + { 0x7C, 0x12, 0x11, 0x12, 0x7C }, // А 0xC0 192 + { 0x7F, 0x49, 0x49, 0x49, 0x31 }, // Б 0xC1 193 + { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // В 0xC2 194 + { 0x7F, 0x01, 0x01, 0x01, 0x01 }, // Г 0xC3 195 + { 0x60, 0x3F, 0x21, 0x3F, 0x60 }, // Д 0xC4 196 + { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // Е 0xC5 197 + { 0x77, 0x08, 0x7F, 0x08, 0x77 }, // Ж 0xC6 198 + { 0x22, 0x41, 0x49, 0x49, 0x36 }, // З 0xC7 199 + { 0x7F, 0x10, 0x08, 0x04, 0x7F }, // И 0xC8 200 + { 0x7E, 0x10, 0x09, 0x04, 0x7E }, // Й 0xC9 201 + { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // К 0xCA 202 + { 0x40, 0x3E, 0x01, 0x01, 0x7F }, // Л 0xCB 203 + { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // М 0xCC 204 + { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // Н 0xCD 205 + { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // О 0xCE 206 + { 0x7F, 0x01, 0x01, 0x01, 0x7F }, // П 0xCF 207 + { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // Р 0xD0 208 + { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // С 0xD1 209 + { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // Т 0xD2 210 + { 0x07, 0x48, 0x48, 0x48, 0x3F }, // У 0xD3 211 + { 0x0E, 0x11, 0x7F, 0x11, 0x0E }, // Ф 0xD4 212 + { 0x63, 0x14, 0x08, 0x14, 0x63 }, // Х 0xD5 213 + { 0x3F, 0x20, 0x20, 0x3F, 0x60 }, // Ц 0xD6 214 + { 0x07, 0x08, 0x08, 0x08, 0x7F }, // Ч 0xD7 215 + { 0x7F, 0x40, 0x7E, 0x40, 0x7F }, // Ш 0xD8 216 + { 0x3F, 0x20, 0x3F, 0x20, 0x7F }, // Щ 0xD9 217 + { 0x01, 0x7F, 0x48, 0x48, 0x30 }, // Ъ 0xDA 218 + { 0x7F, 0x48, 0x30, 0x00, 0x7F }, // Ы 0xDB 219 + { 0x00, 0x7F, 0x48, 0x48, 0x30 }, // Ь 0xDC 220 + { 0x22, 0x41, 0x49, 0x49, 0x3E }, // Э 0xDD 221 + { 0x7F, 0x08, 0x3E, 0x41, 0x3E }, // Ю 0xDE 222 + { 0x46, 0x29, 0x19, 0x09, 0x7F }, // Я 0xDF 223 + { 0x20, 0x54, 0x54, 0x54, 0x78 }, // а 0xE0 224 + { 0x3C, 0x4A, 0x4A, 0x4A, 0x31 }, // б 0xE1 225 + { 0x7C, 0x54, 0x54, 0x28, 0x00 }, // в 0xE2 226 + { 0x7C, 0x04, 0x04, 0x0C, 0x00 }, // г 0xE3 227 + { 0x60, 0x3C, 0x24, 0x3C, 0x60 }, // д 0xE4 228 + { 0x38, 0x54, 0x54, 0x54, 0x18 }, // е 0xE5 229 + { 0x6C, 0x10, 0x7C, 0x10, 0x6C }, // ж 0xE6 230 + { 0x00, 0x44, 0x54, 0x54, 0x28 }, // з 0xE7 231 + { 0x7C, 0x20, 0x10, 0x08, 0x7C }, // и 0xE8 232 + { 0x7C, 0x21, 0x12, 0x09, 0x7C }, // й 0xE9 233 + { 0x7C, 0x10, 0x28, 0x44, 0x00 }, // к 0xEA 234 + { 0x40, 0x38, 0x04, 0x04, 0x7C }, // л 0xEB 235 + { 0x7C, 0x08, 0x10, 0x08, 0x7C }, // м 0xEC 236 + { 0x7C, 0x10, 0x10, 0x10, 0x7C }, // н 0xED 237 + { 0x38, 0x44, 0x44, 0x44, 0x38 }, // о 0xEE 238 + { 0x7C, 0x04, 0x04, 0x04, 0x7C }, // п 0xEF 239 + { 0x7C, 0x14, 0x14, 0x14, 0x08 }, // р 0xF0 240 + { 0x38, 0x44, 0x44, 0x44, 0x00 }, // с 0xF1 241 + { 0x04, 0x04, 0x7C, 0x04, 0x04 }, // т 0xF2 242 + { 0x0C, 0x50, 0x50, 0x50, 0x3C }, // у 0xF3 243 + { 0x08, 0x14, 0x7C, 0x14, 0x08 }, // ф 0xF4 244 + { 0x44, 0x28, 0x10, 0x28, 0x44 }, // х 0xF5 245 + { 0x3C, 0x20, 0x20, 0x3C, 0x60 }, // ц 0xF6 246 + { 0x0C, 0x10, 0x10, 0x10, 0x7C }, // ч 0xF7 247 + { 0x7C, 0x40, 0x7C, 0x40, 0x7C }, // ш 0xF8 248 + { 0x3C, 0x20, 0x3C, 0x20, 0x7C }, // щ 0xF9 249 + { 0x04, 0x7C, 0x50, 0x50, 0x20 }, // ъ 0xFA 250 + { 0x7C, 0x50, 0x20, 0x00, 0x7C }, // ы 0xFB 251 + { 0x00, 0x7C, 0x50, 0x50, 0x20 }, // ь 0xFC 252 + { 0x28, 0x44, 0x54, 0x54, 0x38 }, // э 0xFD 253 + { 0x7C, 0x10, 0x38, 0x44, 0x38 }, // ю 0xFE 254 + { 0x48, 0x54, 0x34, 0x14, 0x7C } // я 0xFF 255 +}; + +#endif /* _N3310_H_ */ +``` + +sc55.c: +```c +/* + * Имя : n3310.c + * + * Описание : Это драйвер для графического LCD от Nokia 3310, а также его китайских клонов. + * Базируется на коде библиотек написанных Sylvain Bissonnette и Fandi Gunawan: + * http://www.microsyl.com/index.php/2010/03/24/nokia-lcd-library/ + * http://fandigunawan.wordpress.com/2008/06/18/lcd-nokia-3310-pcd8544-driver-in-winavravr-gcc/ + * Основные отличия между оригиналом и клоном хорошо описаны в статье от Aheir: + * http://radiokot.ru/articles/29/ + * + * Автор : Xander Gresolio + * Веб-страница : http://we.easyelectronics.ru/profile/XANDER/ + * + * Лицензия : GPL v3.0 + * + * Компилятор : WinAVR, GCC for AVR platform + * + * История : + * Версия 1.0 (06.08.2011) + * + Первая версия + * + Добавлена поддержка китайских клонов LCD Nokia 3310 + * + Полный перевод комментариев к исходному коду драйвера + * + Таблица символов драйвера дополнена кириллицей (упрощенная Windows-1251) + * + Добавлена функция рисования окружностей LcdCircle + * - Исправлены ошибки в проверке корректности координат при вызове функций рисования + * - Исправлена ошибка в функции LcdSingleBar (неверная отрисовка по y) + */ + +#include +#include +#include "sc55.h" + +// Прототипы приватных функций драйвера + +static void LcdSend ( byte data, LcdCmdData cd ); +static void Delay ( void ); + +// Глобальные переменные + +// Кэш в ОЗУ 84*48 бит или 504 байта +static byte LcdCache [ LCD_CACHE_SIZE ]; + +// Чтобы не обновлять весь дисплей, а лишь ту часть что изменилась, +// будем отмечать две границы кэша где произошли изменения. Затем +// можно копировать эту часть кэша между границами в ОЗУ дисплея. +static int LoWaterMark; // нижняя граница +static int HiWaterMark; // верхняя граница + +// Указатель для работы с LcdCache[] +static int LcdCacheIdx; + +// Флаг изменений кэша +static byte UpdateLcd; + + + +/* + * Имя : LcdInit + * Описание : Производит инициализацию порта МК и контроллера LCD + * Аргумент(ы) : Нет + * Возвращаемое значение : Нет + */ +void LcdInit ( void ) +{ + // Pull-up на вывод подключенный к reset дисплея + LCD_PORT |= _BV ( LCD_RST_PIN ); + + // Устанавливаем нужные биты порта на выход + LCD_DDR |= _BV( LCD_RST_PIN ) | _BV( LCD_DC_PIN ) | _BV( LCD_CE_PIN ) | _BV(LCD_DATA_PIN) | _BV(LCD_CLK_PIN); + + // Некалиброванная задержка + Delay(); + + // Дергаем reset + LCD_PORT &= ~( _BV( LCD_RST_PIN ) ); + Delay(); + LCD_PORT |= _BV ( LCD_RST_PIN ); + + // Отключаем LCD контроллер - высокий уровень на SCE + LCD_PORT |= _BV( LCD_CE_PIN ); + + // Отправляем команды дисплею + LcdSend( 0x21, LCD_CMD ); // Включаем расширенный набор команд (LCD Extended Commands) + LcdSend( 0xC8, LCD_CMD ); // Установка контрастности (LCD Vop) + LcdSend( 0x06, LCD_CMD ); // Установка температурного коэффициента (Temp coefficent) + LcdSend( 0x16, LCD_CMD ); // Настройка питания (Bias n=2), siemens + LcdSend( 0x20, LCD_CMD ); // Включаем стандартный набор команд и горизонтальную адресацию (LCD Standard Commands,Horizontal addressing mode) + LcdSend( 0x0C, LCD_CMD ); // Нормальный режим (LCD in normal mode) + + // Первичная очистка дисплея + LcdClear(); + LcdUpdate(); +} + + + +/* + * Имя : LcdClear + * Описание : Очищает дисплей. Далее необходимо выполнить LcdUpdate + * Аргумент(ы) : Нет + * Возвращаемое значение : Нет + */ +void LcdClear ( void ) +{ +// // Очистка кэша дисплея +// int i; +// for ( i = 0; i < LCD_CACHE_SIZE; i++ ) +// { +// LcdCache[i] = 0x00; +// } + + // Оптимизация от Jakub Lasinski (March 14 2009) + memset( LcdCache, 0x00, LCD_CACHE_SIZE ); + + // Сброс указателей границ в максимальное значение + LoWaterMark = 0; + HiWaterMark = LCD_CACHE_SIZE - 1; + + // Установка флага изменений кэша + UpdateLcd = TRUE; +} + + + +/* + * Имя : LcdUpdate + * Описание : Копирует кэш в ОЗУ дисплея + * Аргумент(ы) : Нет + * Возвращаемое значение : Нет + */ +void LcdUpdate (void) +{ + int i; + + if ( LoWaterMark < 0 ) + LoWaterMark = 0; + else if ( LoWaterMark >= LCD_CACHE_SIZE ) + LoWaterMark = LCD_CACHE_SIZE - 1; + + if ( HiWaterMark < 0 ) + HiWaterMark = 0; + else if ( HiWaterMark >= LCD_CACHE_SIZE ) + HiWaterMark = LCD_CACHE_SIZE - 1; + + // Устанавливаем начальный адрес в соответствии к LoWaterMark + LcdSend( 0x80 | ( LoWaterMark % LCD_X_RES ), LCD_CMD ); + LcdSend( 0x40 | ( LoWaterMark / LCD_X_RES ), LCD_CMD ); + + // Обновляем необходимую часть буфера дисплея + for ( i = LoWaterMark; i <= HiWaterMark; i++ ) + { + // Для оригинального дисплея не нужно следить за адресом в буфере, + // можно просто последовательно выводить данные + LcdSend( LcdCache[i], LCD_DATA ); + } + + // Сброс указателей границ в пустоту + LoWaterMark = LCD_CACHE_SIZE - 1; + HiWaterMark = 0; + + // Сброс флага изменений кэша + UpdateLcd = FALSE; +} + + +/* + * Имя : LcdSend + * Описание : Отправляет данные в контроллер дисплея + * Аргумент(ы) : data -> данные для отправки + * cd -> команда или данные (смотри enum в n3310.h) + * Возвращаемое значение : Нет + */ +static void LcdSend ( byte data, LcdCmdData cd ) +{ + // Включаем контроллер дисплея (низкий уровень активный) + LCD_PORT &= ~( _BV( LCD_CE_PIN ) ); + + byte i; + + if (cd == LCD_DATA) + LCD_PORT |= _BV(LCD_DC_PIN); + else + LCD_PORT &= ~_BV(LCD_DC_PIN); + + for (i = 0; i < 8; i++) { + + if ((data >> (7 - i)) & 1) { + LCD_PORT |= _BV(LCD_DATA_PIN); + } else { + LCD_PORT &= ~_BV(LCD_DATA_PIN); + } + + LCD_PORT |= _BV(LCD_CLK_PIN); + LCD_PORT &= ~_BV(LCD_CLK_PIN); + + } + LCD_PORT |= _BV(LCD_DATA_PIN); + LCD_PORT |= _BV(LCD_DC_PIN); + + // Отключаем контроллер дисплея + LCD_PORT |= _BV( LCD_CE_PIN ); +} + + + +/* + * Имя : LcdContrast + * Описание : Устанавливает контрастность дисплея + * Аргумент(ы) : контраст -> значение от 0x00 к 0x7F + * Возвращаемое значение : Нет + */ +void LcdContrast ( byte contrast ) +{ + LcdSend( 0x21, LCD_CMD ); // Расширенный набор команд + LcdSend( 0x80 | contrast, LCD_CMD ); // Установка уровня контрастности + LcdSend( 0x20, LCD_CMD ); // Стандартный набор команд, горизонтальная адресация +} + + + +/* + * Имя : Delay + * Описание : Некалиброванная задержка для процедуры инициализации LCD + * Аргумент(ы) : Нет + * Возвращаемое значение : Нет + */ +static void Delay ( void ) +{ + int i; + + for ( i = -32000; i < 32000; i++ ); +} + + + +/* + * Имя : LcdGotoXYFont + * Описание : Устанавливает курсор в позицию x,y относительно стандартного размера шрифта + * Аргумент(ы) : x,y -> координаты новой позиции курсора. Значения: 0,0 .. 13,5 + * Возвращаемое значение : смотри возвращаемое значение в n3310.h + */ +byte LcdGotoXYFont ( byte x, byte y ) +{ + // Проверка границ + if( x > LCD_COLS || y > LCD_LINES ) return OUT_OF_BORDER; + + // Вычисление указателя. Определен как адрес в пределах 504 байт + LcdCacheIdx = x * LCD_LINES + y * LCD_X_RES; + return OK; +} + + + +/* + * Имя : LcdChr + * Описание : Выводит символ в текущей позиции курсора, затем инкрементирует положение курсора + * Аргумент(ы) : size -> размер шрифта. Смотри enum в n3310.h + * ch -> символ для вывода + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + */ +byte LcdChr ( LcdFontSize size, byte ch ) +{ + byte i, c; + byte b1, b2; + int tmpIdx; + + if ( LcdCacheIdx < LoWaterMark ) + { + // Обновляем нижнюю границу + LoWaterMark = LcdCacheIdx; + } + + if ( (ch >= 0x20) && (ch <= 0x7F) ) + { + // Смещение в таблице для символов ASCII[0x20-0x7F] + ch -= 32; + } + else if ( ch >= 0xC0 ) + { + // Смещение в таблице для символов CP1251[0xC0-0xFF] + ch -= 96; + } + else + { + // Остальные игнорируем (их просто нет в таблице для экономии памяти) + ch = 95; + } + + if ( size == FONT_1X ) + { + for ( i = 0; i < 5; i++ ) + { + // Копируем вид символа из таблицы в кэш + LcdCache[LcdCacheIdx++] = pgm_read_byte( &(FontLookup[ch][i]) ) << 1; + } + } + else if ( size == FONT_2X ) + { + tmpIdx = LcdCacheIdx - LCD_X_RES; + + if ( tmpIdx < LoWaterMark ) + { + LoWaterMark = tmpIdx; + } + + if ( tmpIdx < 0 ) return OUT_OF_BORDER; + + for ( i = 0; i < 5; i++ ) + { + // Копируем вид символа из таблицы у временную переменную + c = pgm_read_byte(&(FontLookup[ch][i])) << 1; + // Увеличиваем картинку + // Первую часть + b1 = (c & 0x01) * 3; + b1 |= (c & 0x02) * 6; + b1 |= (c & 0x04) * 12; + b1 |= (c & 0x08) * 24; + + c >>= 4; + // Вторую часть + b2 = (c & 0x01) * 3; + b2 |= (c & 0x02) * 6; + b2 |= (c & 0x04) * 12; + b2 |= (c & 0x08) * 24; + + // Копируем две части в кэш + LcdCache[tmpIdx++] = b1; + LcdCache[tmpIdx++] = b1; + LcdCache[tmpIdx + LCD_X_RES - 2] = b2; + LcdCache[tmpIdx + LCD_X_RES - 1] = b2; + } + + // Обновляем x координату курсора + LcdCacheIdx = (LcdCacheIdx + 11) % LCD_CACHE_SIZE; + } + + if ( LcdCacheIdx > HiWaterMark ) + { + // Обновляем верхнюю границу + HiWaterMark = LcdCacheIdx; + } + + // Горизонтальный разрыв между символами + LcdCache[LcdCacheIdx] = 0x00; + // Если достигли позицию указателя LCD_CACHE_SIZE - 1, переходим в начало + if(LcdCacheIdx == (LCD_CACHE_SIZE - 1) ) + { + LcdCacheIdx = 0; + return OK_WITH_WRAP; + } + // Иначе просто инкрементируем указатель + LcdCacheIdx++; + return OK; +} + + + +/* + * Имя : LcdStr + * Описание : Эта функция предназначена для печати строки которая хранится в RAM + * Аргумент(ы) : size -> размер шрифта. Смотри enum в n3310.h + * dataArray -> массив содержащий строку которую нужно напечатать + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + */ +byte LcdStr ( LcdFontSize size, byte dataArray[] ) +{ + byte tmpIdx=0; + byte response; + while( dataArray[ tmpIdx ] != '\0' ) + { + // Выводим символ + response = LcdChr( size, dataArray[ tmpIdx ] ); + // Не стоит волноваться если произойдет OUT_OF_BORDER, + // строка будет печататься дальше из начала дисплея + if( response == OUT_OF_BORDER) + return OUT_OF_BORDER; + // Увеличиваем указатель + tmpIdx++; + } + return OK; +} + + + +/* + * Имя : LcdFStr + * Описание : Эта функция предназначена для печати строки которая хранится в Flash ROM + * Аргумент(ы) : size -> размер шрифта. Смотри enum в n3310.h + * dataPtr -> указатель на строку которую нужно напечатать + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + * Пример : LcdFStr(FONT_1X, PSTR("Hello World")); + * LcdFStr(FONT_1X, &name_of_string_as_array); + */ +byte LcdFStr ( LcdFontSize size, const byte *dataPtr ) +{ + byte c; + byte response; + for ( c = pgm_read_byte( dataPtr ); c; ++dataPtr, c = pgm_read_byte( dataPtr ) ) + { + // Выводим символ + response = LcdChr( size, c ); + if(response == OUT_OF_BORDER) + return OUT_OF_BORDER; + } + + return OK; +} + + + +/* + * Имя : LcdPixel + * Описание : Отображает пиксель по абсолютным координатам (x,y) + * Аргумент(ы) : x,y -> абсолютные координаты пикселя + * mode -> Off, On или Xor. Смотри enum в n3310.h + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + */ +byte LcdPixel ( byte x, byte y, LcdPixelMode mode ) +{ + int index; + byte offset; + byte data; + + // Защита от выхода за пределы + if ( x >= LCD_X_RES || y >= LCD_Y_RES) return OUT_OF_BORDER; + + // Пересчет индекса и смещения + index = ( ( y / LCD_LINES ) * LCD_X_RES ) + x; + offset = y - ( ( y / 8) * LCD_LINES ); + + data = LcdCache[ index ]; + + // Обработка битов + + // Режим PIXEL_OFF + if ( mode == PIXEL_OFF ) + { + data &= ( ~( 0x01 << offset ) ); + } + // Режим PIXEL_ON + else if ( mode == PIXEL_ON ) + { + data |= ( 0x01 << offset ); + } + // Режим PIXEL_XOR + else if ( mode == PIXEL_XOR ) + { + data ^= ( 0x01 << offset ); + } + + // Окончательный результат копируем в кэш + LcdCache[ index ] = data; + + if ( index < LoWaterMark ) + { + // Обновляем нижнюю границу + LoWaterMark = index; + } + + if ( index > HiWaterMark ) + { + // Обновляем верхнюю границу + HiWaterMark = index; + } + return OK; +} + + + +/* + * Имя : LcdLine + * Описание : Рисует линию между двумя точками на дисплее (алгоритм Брезенхэма) + * Аргумент(ы) : x1, y1 -> абсолютные координаты начала линии + * x2, y2 -> абсолютные координаты конца линии + * mode -> Off, On или Xor. Смотри enum в n3310.h + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + */ +byte LcdLine ( byte x1, byte y1, byte x2, byte y2, LcdPixelMode mode ) +{ + int dx, dy, stepx, stepy, fraction; + byte response; + + // dy y2 - y1 + // -- = ------- + // dx x2 - x1 + + dy = y2 - y1; + dx = x2 - x1; + + // dy отрицательное + if ( dy < 0 ) + { + dy = -dy; + stepy = -1; + } + else + { + stepy = 1; + } + + // dx отрицательное + if ( dx < 0 ) + { + dx = -dx; + stepx = -1; + } + else + { + stepx = 1; + } + + dx <<= 1; + dy <<= 1; + + // Рисуем начальную точку + response = LcdPixel( x1, y1, mode ); + if(response) + return response; + + // Рисуем следующие точки до конца + if ( dx > dy ) + { + fraction = dy - ( dx >> 1); + while ( x1 != x2 ) + { + if ( fraction >= 0 ) + { + y1 += stepy; + fraction -= dx; + } + x1 += stepx; + fraction += dy; + + response = LcdPixel( x1, y1, mode ); + if(response) + return response; + + } + } + else + { + fraction = dx - ( dy >> 1); + while ( y1 != y2 ) + { + if ( fraction >= 0 ) + { + x1 += stepx; + fraction -= dy; + } + y1 += stepy; + fraction += dx; + + response = LcdPixel( x1, y1, mode ); + if(response) + return response; + } + } + + // Установка флага изменений кэша + UpdateLcd = TRUE; + return OK; +} + + + +/* + * Имя : LcdCircle + * Описание : Рисует окружность (алгоритм Брезенхэма) + * Аргумент(ы) : x, y -> абсолютные координаты центра + * radius -> радиус окружности + * mode -> Off, On или Xor. Смотри enum в n3310.h + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + */ +byte LcdCircle(byte x, byte y, byte radius, LcdPixelMode mode) +{ + signed char xc = 0; + signed char yc = 0; + signed char p = 0; + + if ( x >= LCD_X_RES || y >= LCD_Y_RES) return OUT_OF_BORDER; + + yc = radius; + p = 3 - (radius<<1); + while (xc <= yc) + { + LcdPixel(x + xc, y + yc, mode); + LcdPixel(x + xc, y - yc, mode); + LcdPixel(x - xc, y + yc, mode); + LcdPixel(x - xc, y - yc, mode); + LcdPixel(x + yc, y + xc, mode); + LcdPixel(x + yc, y - xc, mode); + LcdPixel(x - yc, y + xc, mode); + LcdPixel(x - yc, y - xc, mode); + if (p < 0) p += (xc++ << 2) + 6; + else p += ((xc++ - yc--)<<2) + 10; + } + + // Установка флага изменений кэша + UpdateLcd = TRUE; + return OK; +} + + +/* + * Имя : LcdSingleBar + * Описание : Рисует один закрашенный прямоугольник + * Аргумент(ы) : baseX -> абсолютная координата x (нижний левый угол) + * baseY -> абсолютная координата y (нижний левый угол) + * height -> высота (в пикселях) + * width -> ширина (в пикселях) + * mode -> Off, On или Xor. Смотри enum в n3310.h + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + */ +byte LcdSingleBar ( byte baseX, byte baseY, byte height, byte width, LcdPixelMode mode ) +{ + byte tmpIdxX,tmpIdxY,tmp; + + byte response; + + // Проверка границ + if ( ( baseX >= LCD_X_RES) || ( baseY >= LCD_Y_RES) ) return OUT_OF_BORDER; + + if ( height > baseY ) + tmp = 0; + else + tmp = baseY - height + 1; + + // Рисование линий + for ( tmpIdxY = tmp; tmpIdxY <= baseY; tmpIdxY++ ) + { + for ( tmpIdxX = baseX; tmpIdxX < (baseX + width); tmpIdxX++ ) + { + response = LcdPixel( tmpIdxX, tmpIdxY, mode ); + if(response) + return response; + + } + } + + // Установка флага изменений кэша + UpdateLcd = TRUE; + return OK; +} + + + +/* + * Имя : LcdBars + * Описание : Рисует группу закрашенных прямоугольников (в режиме PIXEL_ON) + * Аргумент(ы) : data[] -> данные которые нужно отобразить + * numbBars -> количество прямоугольников + * width -> ширина (в пикселях) + * multiplier -> множитель для высоты + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + * Примечание : Пожалуйста проверьте значения EMPTY_SPACE_BARS, BAR_X, BAR_Y в n3310.h + * Пример : byte example[5] = {1, 2, 3, 4, 5}; + * LcdBars(example, 5, 3, 2); + */ +byte LcdBars ( byte data[], byte numbBars, byte width, byte multiplier ) +{ + byte b; + byte tmpIdx = 0; + byte response; + + for ( b = 0; b < numbBars ; b++ ) + { + // Защита от выхода за пределы + if ( tmpIdx > LCD_X_RES - 1 ) return OUT_OF_BORDER; + + // Расчет значения x + tmpIdx = ((width + EMPTY_SPACE_BARS) * b) + BAR_X; + + // Рисуем один прямоугольник + response = LcdSingleBar( tmpIdx, BAR_Y, data[b] * multiplier, width, PIXEL_ON); + if(response == OUT_OF_BORDER) + return response; + } + + // Установка флага изменений кэша + UpdateLcd = TRUE; + return OK; + +} + + + +/* + * Имя : LcdRect + * Описание : Рисует незакрашенный прямоугольник + * Аргумент(ы) : x1 -> абсолютная координата x левого верхнего угла + * y1 -> абсолютная координата y левого верхнего угла + * x2 -> абсолютная координата x правого нижнего угла + * y2 -> абсолютная координата y правого нижнего угла + * mode -> Off, On или Xor. Смотри enum в n3310.h + * Возвращаемое значение : смотри возвращаемое значение в n3310lcd.h + */ +byte LcdRect ( byte x1, byte y1, byte x2, byte y2, LcdPixelMode mode ) +{ + byte tmpIdx; + + // Проверка границ + if ( ( x1 >= LCD_X_RES) || ( x2 >= LCD_X_RES) || ( y1 >= LCD_Y_RES) || ( y2 >= LCD_Y_RES) ) + return OUT_OF_BORDER; + + if ( ( x2 > x1 ) && ( y2 > y1 ) ) + { + // Рисуем горизонтальные линии + for ( tmpIdx = x1; tmpIdx <= x2; tmpIdx++ ) + { + LcdPixel( tmpIdx, y1, mode ); + LcdPixel( tmpIdx, y2, mode ); + } + + // Рисуем вертикальные линии + for ( tmpIdx = y1; tmpIdx <= y2; tmpIdx++ ) + { + LcdPixel( x1, tmpIdx, mode ); + LcdPixel( x2, tmpIdx, mode ); + } + + // Установка флага изменений кэша + UpdateLcd = TRUE; + } + return OK; +} + + + +/* + * Имя : LcdImage + * Описание : Рисует картинку из массива сохраненного в Flash ROM + * Аргумент(ы) : Указатель на массив картинки + * Возвращаемое значение : Нет + */ +void LcdImage ( const byte *imageData ) +{ +// // Инициализация указателя кэша +// LcdCacheIdx = 0; +// // В пределах кэша +// for ( LcdCacheIdx = 0; LcdCacheIdx < LCD_CACHE_SIZE; LcdCacheIdx++ ) +// { +// // Копируем данные из массива в кэш +// LcdCache[LcdCacheIdx] = pgm_read_byte( imageData++ ); +// } + + // Оптимизация от Jakub Lasinski (March 14 2009) + memcpy_P( LcdCache, imageData, LCD_CACHE_SIZE ); // Тоже самое что и выше, но занимает меньше памяти и быстрее выполняется + + // Сброс указателей границ в максимальное значение + LoWaterMark = 0; + HiWaterMark = LCD_CACHE_SIZE - 1; + + // Установка флага изменений кэша + UpdateLcd = TRUE; +} +``` + +main.c: +```c +#include +#include "sc55.h" + + +int main() { + LcdInit(); + LcdContrast(0x45); + while (1) { + LcdClear(); + LcdRect(0, 0, LCD_X_RES - 2, LCD_Y_RES - 2, PIXEL_ON); + LcdLine(0, 0, LCD_X_RES - 2, LCD_Y_RES - 2, PIXEL_ON); + LcdLine(0, LCD_Y_RES - 2, LCD_X_RES - 2, 0, PIXEL_ON); + LcdUpdate(); + _delay_ms(1000); + + LcdClear(); + LcdGotoXYFont(0, 2); + LcdStr(FONT_2X, "Привет,"); + LcdGotoXYFont(0, 4); + LcdStr(FONT_2X, "мир!"); + LcdUpdate(); + _delay_ms(1000); + } + +} +``` + +![|400](helloworld.jpg) ![|400](lines.jpg) \ No newline at end of file diff --git a/content/posts/avr-siemens-lcd/lcd.jpg b/content/posts/avr-siemens-lcd/lcd.jpg new file mode 100644 index 0000000..6faa59a Binary files /dev/null and b/content/posts/avr-siemens-lcd/lcd.jpg differ diff --git a/content/posts/avr-siemens-lcd/lines.jpg b/content/posts/avr-siemens-lcd/lines.jpg new file mode 100644 index 0000000..a3bed0e Binary files /dev/null and b/content/posts/avr-siemens-lcd/lines.jpg differ diff --git a/content/posts/avr-siemens-lcd/lph8684.png b/content/posts/avr-siemens-lcd/lph8684.png new file mode 100644 index 0000000..aa3d0a8 Binary files /dev/null and b/content/posts/avr-siemens-lcd/lph8684.png differ diff --git a/content/posts/avr-siemens-lcd/miniature.jpg b/content/posts/avr-siemens-lcd/miniature.jpg new file mode 100644 index 0000000..f0abcfe Binary files /dev/null and b/content/posts/avr-siemens-lcd/miniature.jpg differ diff --git a/content/posts/codeblocks-avr-linker-error/cb_compilerselect.png b/content/posts/codeblocks-avr-linker-error/cb_compilerselect.png new file mode 100644 index 0000000..26e1380 Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/cb_compilerselect.png differ diff --git a/content/posts/codeblocks-avr-linker-error/cb_error.png b/content/posts/codeblocks-avr-linker-error/cb_error.png new file mode 100644 index 0000000..aec5b3c Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/cb_error.png differ diff --git a/content/posts/codeblocks-avr-linker-error/cb_includeset.png b/content/posts/codeblocks-avr-linker-error/cb_includeset.png new file mode 100644 index 0000000..3587028 Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/cb_includeset.png differ diff --git a/content/posts/codeblocks-avr-linker-error/cb_libset.png b/content/posts/codeblocks-avr-linker-error/cb_libset.png new file mode 100644 index 0000000..d17ab1a Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/cb_libset.png differ diff --git a/content/posts/codeblocks-avr-linker-error/cb_libset1.png b/content/posts/codeblocks-avr-linker-error/cb_libset1.png new file mode 100644 index 0000000..0117de4 Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/cb_libset1.png differ diff --git a/content/posts/codeblocks-avr-linker-error/cb_libset2.png b/content/posts/codeblocks-avr-linker-error/cb_libset2.png new file mode 100644 index 0000000..05475c7 Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/cb_libset2.png differ diff --git a/content/posts/codeblocks-avr-linker-error/cb_options.png b/content/posts/codeblocks-avr-linker-error/cb_options.png new file mode 100644 index 0000000..1ac4c79 Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/cb_options.png differ diff --git a/content/posts/codeblocks-avr-linker-error/index.md b/content/posts/codeblocks-avr-linker-error/index.md new file mode 100644 index 0000000..1712099 --- /dev/null +++ b/content/posts/codeblocks-avr-linker-error/index.md @@ -0,0 +1,42 @@ +--- +title: "Избавляемся от undefined reference to `__mulqi3' в Code::Blocks" +categories: ["cpp", "archive"] +date: 2016-11-29T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Мне нравится Code::Blocks. Замечательная IDE, которая умеет всё. И вот сравнительно недавно начал использовать эту среду для написания программ для AVR. Всё шло замечательно, но стоило лишь использовать sprintf, программа перестала компилироваться, линковщик выдавал ошибку undefined reference to `__mulqi3'. + +![|](cb_error.png) + +После гуглений оказалось, что автонаходитель тулчейна работает немного некорректно. Что ж, идём исправлять. Открываем настройки компиляторов. + +![|](cb_options.png) + +Выбираем **GNU GCC Compiler for AVR**. + +![|](cb_compilerselect.png) + +Открываем вкладку Search **directories**, в ней вкладку **Linker**. + +![|](cb_libset1.png) + +И удаляем суффикс avr в пути. + +Например, + +было `d:\_compilers\avr8-gnu-toolchain\avr\lib` + +стало `d:\_compilers\avr8-gnu-toolchain\lib` + +![|](cb_libset.png) + +![|](cb_libset2.png) + +Те же манипуляции производим с вкладкой **Compiler**. + +![|](cb_includeset.png) + +Сохраняем и спокойно работаем дальше :) \ No newline at end of file diff --git a/content/posts/codeblocks-avr-linker-error/miniature.jpg b/content/posts/codeblocks-avr-linker-error/miniature.jpg new file mode 100644 index 0000000..b2cf20c Binary files /dev/null and b/content/posts/codeblocks-avr-linker-error/miniature.jpg differ diff --git a/content/posts/dualshock-avr-usb/connections.png b/content/posts/dualshock-avr-usb/connections.png new file mode 100644 index 0000000..056c11b Binary files /dev/null and b/content/posts/dualshock-avr-usb/connections.png differ diff --git a/content/posts/dualshock-avr-usb/fusebits.png b/content/posts/dualshock-avr-usb/fusebits.png new file mode 100644 index 0000000..eb3b1c5 Binary files /dev/null and b/content/posts/dualshock-avr-usb/fusebits.png differ diff --git a/content/posts/dualshock-avr-usb/gamepads.jpg b/content/posts/dualshock-avr-usb/gamepads.jpg new file mode 100644 index 0000000..a8dbbb6 Binary files /dev/null and b/content/posts/dualshock-avr-usb/gamepads.jpg differ diff --git a/content/posts/dualshock-avr-usb/index.md b/content/posts/dualshock-avr-usb/index.md new file mode 100644 index 0000000..33a3e4c --- /dev/null +++ b/content/posts/dualshock-avr-usb/index.md @@ -0,0 +1,83 @@ +--- +title: "Подключение геймпадов от PlayStation к USB" +categories: ["mcu", "archive"] +date: 2015-08-13T00:00:00+03:00 +draft: false +featured_image: gamepads.jpg +--- + + +Недавно на барахолке повезло купить два геймпада DualShock2 по очень таки низкой цене. Но вот незадача - у геймпадов PlayStation свой разъем и общаются с консолью они по интерфейсу SPI. Пару минут гугла и находим сайт со схемой переходника PSX->USB на ATmega8. Ну что ж, берёмся за дело. + + +Нам понадобятся: + +* ATmega8 +* 2 резистора 22-68 Ом +* резистор 1.5-2.2 кОм +* 2 стабилитрона 3.6в +* кварцевый резонатор 12 МГц +* 2 конденсатора 22 пФ +* светодиод и резистор для него (100-500 Ом) +* USB шнур + + +Схема следующая: + +![Схема|642](schematic.gif) + +![Подключение контроллеров|276](connections.png) + +Назначение контактов в геймпадах уже было подписано заботливыми (наверное) китайцами. + +![Плата с распиновкой|300](pcb_pins.jpg) + +**DI = DAT** + +**DO = CMD** + +**CS = SEL** + +![Распиновка разъема|](pinout.png) + +Мегу я прошил ещё до пайки. Прошивку заливал вторую (psx2.hex), так как геймпадов у меня два. Фьюзы выставляются на тактирование от внешнего резонатора (High Freq.) + +![Фьюзы для CodeVisionAvr|](fusebits.png) + +Если честно, мне лень было травить плату для такой схемы, так что я просто расцарапал и залудил кусочек стеклотекстолита. Затем напаял микросхему сверху. Вышло следующее: + +![|300](shit1.jpg) + +Напаял основные части: + +![|300](shit2.jpg) + +В качестве корпуса я взял старый блок питания от радиотелефона. + +Просверлил в нём дырки, протянул через них провода от геймпадов, припаял: + +![|300](shit3.jpg) + +Вот такая красота получилась: + +![|300](gamepads.jpg) + +Так устройство распознаётся в системе: ![|295](pc1.png) + +Откалибровать геймпады можно зайдя в **Панель управления -> Устройства и принтеры** (Win7). Там находим наше устройство: + +![|525](pc2.png) + +Щёлкаем правой кнопкой -> **Параметры игровых устройств управления** + +![|808](pc3.png) + +Если при нажатии кнопок на геймпаде в окошке ничего не меняется, что что-то пошло не так. + +**Ссылки:** + +[Прошивка и исходник](psx_to_usb.zip) + +[Сайт-источник](http://www.radiomexanik.spb.ru/kompyuternaya-elektronika/podklyuchenie-dzhoystikov-ot-igrovyih-pristavok-k-shine-usb.html) + +[Распиновка отсюда](http://radiokot.ru/lab/controller/17/) \ No newline at end of file diff --git a/content/posts/dualshock-avr-usb/pc1.png b/content/posts/dualshock-avr-usb/pc1.png new file mode 100644 index 0000000..42c8f73 Binary files /dev/null and b/content/posts/dualshock-avr-usb/pc1.png differ diff --git a/content/posts/dualshock-avr-usb/pc2.png b/content/posts/dualshock-avr-usb/pc2.png new file mode 100644 index 0000000..56e4ecc Binary files /dev/null and b/content/posts/dualshock-avr-usb/pc2.png differ diff --git a/content/posts/dualshock-avr-usb/pc3.png b/content/posts/dualshock-avr-usb/pc3.png new file mode 100644 index 0000000..18f91db Binary files /dev/null and b/content/posts/dualshock-avr-usb/pc3.png differ diff --git a/content/posts/dualshock-avr-usb/pcb_pins.jpg b/content/posts/dualshock-avr-usb/pcb_pins.jpg new file mode 100644 index 0000000..1e62924 Binary files /dev/null and b/content/posts/dualshock-avr-usb/pcb_pins.jpg differ diff --git a/content/posts/dualshock-avr-usb/pinout.png b/content/posts/dualshock-avr-usb/pinout.png new file mode 100644 index 0000000..1539f85 Binary files /dev/null and b/content/posts/dualshock-avr-usb/pinout.png differ diff --git a/content/posts/dualshock-avr-usb/psx_to_usb.zip b/content/posts/dualshock-avr-usb/psx_to_usb.zip new file mode 100644 index 0000000..2b36337 Binary files /dev/null and b/content/posts/dualshock-avr-usb/psx_to_usb.zip differ diff --git a/content/posts/dualshock-avr-usb/schematic.gif b/content/posts/dualshock-avr-usb/schematic.gif new file mode 100644 index 0000000..553ba94 Binary files /dev/null and b/content/posts/dualshock-avr-usb/schematic.gif differ diff --git a/content/posts/dualshock-avr-usb/shit1.jpg b/content/posts/dualshock-avr-usb/shit1.jpg new file mode 100644 index 0000000..16be490 Binary files /dev/null and b/content/posts/dualshock-avr-usb/shit1.jpg differ diff --git a/content/posts/dualshock-avr-usb/shit2.jpg b/content/posts/dualshock-avr-usb/shit2.jpg new file mode 100644 index 0000000..368bfe5 Binary files /dev/null and b/content/posts/dualshock-avr-usb/shit2.jpg differ diff --git a/content/posts/dualshock-avr-usb/shit3.jpg b/content/posts/dualshock-avr-usb/shit3.jpg new file mode 100644 index 0000000..6a83022 Binary files /dev/null and b/content/posts/dualshock-avr-usb/shit3.jpg differ diff --git a/content/posts/eclipse-msys2-mingw/buildfail.png b/content/posts/eclipse-msys2-mingw/buildfail.png new file mode 100644 index 0000000..ff7ec58 Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/buildfail.png differ diff --git a/content/posts/eclipse-msys2-mingw/buildok.png b/content/posts/eclipse-msys2-mingw/buildok.png new file mode 100644 index 0000000..1a8cfd3 Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/buildok.png differ diff --git a/content/posts/eclipse-msys2-mingw/debug.png b/content/posts/eclipse-msys2-mingw/debug.png new file mode 100644 index 0000000..1ae4fcb Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/debug.png differ diff --git a/content/posts/eclipse-msys2-mingw/index.md b/content/posts/eclipse-msys2-mingw/index.md new file mode 100644 index 0000000..9dfaa27 --- /dev/null +++ b/content/posts/eclipse-msys2-mingw/index.md @@ -0,0 +1,54 @@ +--- +title: "Eclipse CDT и MSYS2, учим видеть MinGW" +categories: ["cpp", "archive"] +date: 2019-07-15T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Вот захотелось Eclipse попробовать в качестве среды разработки для C++. Везде в списках IDE для C++ она фигурирует. Иногда даже как лучшая. Что ж, будем пробовать. + + + +Пользуюсь я пакетом MSYS2, с установленным MinGW, который давным-давно сидит в PATH. После наведения красоты (спорно, конечно) при создании нового проекта мы видим это: + +![Где MinGW?](whereismingw.png "Где MinGW?") + +Где, спрашивается, MinGW? Он должен присутствовать в списке инструментария, но его нет. Лезем в [FAQ](https://github.com/eclipse-cdt/cdt/tree/main/FAQ#i-installed-mingw-toolchain-on-my-pc-but-eclipse-wont-find-it) пытаемся выполнить все пункты, ничего всё так же не находится. Однако в конце замечаем следующие строки: + +> Despite having g++.exe or gcc.exe on your PATH and having defined MINGW\_HOME, you may still get a “Toolchain "MinGW GCC" is not detected” message (CDT 8.4 on Luna 4.4.0). Make sure that a file called "mingw32-gcc.exe" exists in MINGW\_HOME\\bin. If it doesn't exist (which happens with MinGW-W64), copy a -gcc.exe file (e.g. i686-w64-mingw32-gcc.exe) to mingw32-gcc.exe. If the dreaded message still lingers around, reboot your system (don't just logout and login). + +Ага! Значит, Eclipse ищет не **gcc**, а **mingw32-gcc**. Которого у нас нет: + +![Нет тут mingw32-gcc](mingw32-gcc-missing.png "Нет тут mingw32-gcc") + +В официальном FAQ, как уже можно было заметить, советуют создать копию **gcc.exe** и назвать её **mingw32-gcc.exe**. Но мы поступим умнее. Начиная с Vista, в Windows присутствует утилита [mklink](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/mklink). Для создания символических ссылок, прям как в Linux. Открываем окно команд (у меня cmder) от **имени администратора**, переходим в каталог mingw32/bin и создаём ссылку: + +![mklink](mklink.png) + +```cmd +mklink mingw32-gcc.exe gcc.exe +``` + +Не знаю, нужно ли создавать ссылки для остальных частей комплекта, но для того, чтобы MinGW определился в Eclipse, этого достаточно. Проверяем: + +![MinGW найден](mingwfound.png "MinGW найден") + +Проверяем компилируется ли Hello World проект: + +![Ошибка сборки](buildfail.png "Ошибка сборки") + +Нет. Лезем в конфигурацию и видим, что выбран не тот комплект, который мы выбирали при создании проекта. Странно. Выбираем нужный: + +![Выбор комплекта](settool.png "Выбор комплекта") + +Пробуем снова: + +![Успешная сборка](buildok.png "Успешная сборка") + +Собирается. И запускается, если кликнуть правой кнопкой по бинарю -> Run As -> Local C/C++ Application. Это создаст конфигурацию для последующих запусков. Отладчик тоже работает: + +![Всё работает](debug.png "Всё работает") + +В итоге, не без геморроя, но всё завелось. Как и обычно, впрочем :) \ No newline at end of file diff --git a/content/posts/eclipse-msys2-mingw/mingw32-gcc-missing.png b/content/posts/eclipse-msys2-mingw/mingw32-gcc-missing.png new file mode 100644 index 0000000..ccbb148 Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/mingw32-gcc-missing.png differ diff --git a/content/posts/eclipse-msys2-mingw/mingwfound.png b/content/posts/eclipse-msys2-mingw/mingwfound.png new file mode 100644 index 0000000..7966073 Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/mingwfound.png differ diff --git a/content/posts/eclipse-msys2-mingw/miniature.jpg b/content/posts/eclipse-msys2-mingw/miniature.jpg new file mode 100644 index 0000000..2bbdfc1 Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/miniature.jpg differ diff --git a/content/posts/eclipse-msys2-mingw/mklink.png b/content/posts/eclipse-msys2-mingw/mklink.png new file mode 100644 index 0000000..203efde Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/mklink.png differ diff --git a/content/posts/eclipse-msys2-mingw/settool.png b/content/posts/eclipse-msys2-mingw/settool.png new file mode 100644 index 0000000..a1f91ad Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/settool.png differ diff --git a/content/posts/eclipse-msys2-mingw/whereismingw.png b/content/posts/eclipse-msys2-mingw/whereismingw.png new file mode 100644 index 0000000..2b86b28 Binary files /dev/null and b/content/posts/eclipse-msys2-mingw/whereismingw.png differ diff --git a/content/posts/fltk-apps/app.png b/content/posts/fltk-apps/app.png new file mode 100644 index 0000000..715cb0b Binary files /dev/null and b/content/posts/fltk-apps/app.png differ diff --git a/content/posts/fltk-apps/gimp.png b/content/posts/fltk-apps/gimp.png new file mode 100644 index 0000000..9db9ea1 Binary files /dev/null and b/content/posts/fltk-apps/gimp.png differ diff --git a/content/posts/fltk-apps/index.md b/content/posts/fltk-apps/index.md new file mode 100644 index 0000000..18a25f2 --- /dev/null +++ b/content/posts/fltk-apps/index.md @@ -0,0 +1,187 @@ +--- +title: "FLTK - пишем маленькие кросс-платформенные приложения с олдскульным интерфейсом" +categories: ["cpp", "archive"] +date: 2015-08-19T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Иногда требуется написать кросс-платформенное приложение с небольшим размером. Для управления микроконтроллером, например. Или [рисования иконок для дисплеев](/avr-lcd-images). Но использовать кросс-платформенные библиотеки вроде Qt, WxWidgets не имеет смысла - весят они ну очень много. Неудобно получается, когда приложение весит 100кб, а графическая библиотека для него – под 30Мб. + +На помощь к нам приходит FLTK – Fast, Light Toolkit. + + + +Библиотека распространяется в виде исходного кода и скачивается с сайта [fltk.org](http://www.fltk.org/software.php"). Значит, сейчас будем её собирать. + +Весь процесс описывается для Windows, собираем компилятором **MinGw**. Если у вас его нет – [вперёд скачивать](https://sourceforge.net/downloads/mingw). Разделим процесс на две части. + +# Часть первая – компиляция библиотеки + +Итак, начнём. Скачиваем последнюю версию FLTK с официального сайта. Архив должен называться fltk-версия-**source**.tar.gz. Распаковываем его в любое удобное место. Я распаковал его прямо на на диск C в папку fltk-src. + +В распакованном виде всё должно выглядеть так: + +![src](src.png) + +Теперь нам нужно запустить MSYS. Переходим `туда_куда_установлен_MinGw\msys\1.0` и запускаем там msys.bat. + +![mingw1](mingw1.png) + +Вводим туда `cd /диск/папка_с_fltk` + +![mingw2](mingw2.png) + +Потом вводим `./configure --enable-threads --enable-localjpeg --enable-localzlib --enable-localpng` и ждём. + +![mingw3](mingw3.png) + +Далее следует ввести `make` и ждать. Можно пойти чай заварить. + +![mingw4](mingw4.png) + +Теперь копируем библиотеки в компилятор. Для этого вводим `make install` + +![mingw5](mingw5.png) + +Всё, что получилось складывается в папку `туда_куда_установлен_MinGw\msys\1.0\local`. Для удобства я перенёс эти папки в корень MinGw. + +Всё, библиотека готова к использованию. + +# Часть вторая – пишем программу + +Теперь мы можем написать тестовое приложение, используя эту библиотеку. Писать будем программу, которая будет считать количество нарисованных пикселей. + +Для начала нужно нарисовать макет нашей программы (о FLUID я узнал позже). Я нарисовал в GIMP. + +![gimp](gimp.png) + +Зачем это делать? Всё просто. У каждого элемента в окне есть свои координаты. И чтобы не ставить элементы наугад, можно просто навести мышку на точку в графическом редакторе и узнать координаты. Исходя из этого всего пишем программу. + +fltk_test.cpp: +```cpp +#include +#include +#include +#include +#include +#include +#include + +#define CANVAS_X 10 +#define CANVAS_Y 10 +#define CANVAS_WIDTH 180 +#define CANVAS_HEIGHT 100 +#define GRID_LEN 5 // размер зерна в холсте + +Fl_Box *count_label; +char buf[16]; + +struct point { + int x, y; +}; + +typedef std::map, point> PointMap; // карта с координатами пикселей +PointMap pixels; + + +class PaintWindow : public Fl_Window { //немного модифицируем стандартное окно + +public: + + PaintWindow(int w, int h, char const *title) : Fl_Window(w, h, title) { + + } + + void setpixel(int x, int y, bool add) { + std::pair p = std::make_pair(x * GRID_LEN, y * GRID_LEN); // с помощью древней магии мы используем два аргумента как ключ к карте пикселей + + if (add) { + point pixel; + pixel.x = x * GRID_LEN; + pixel.y = y * GRID_LEN; + pixels[p] = pixel; + } else { + pixels.erase(p); + } + + sprintf(buf, "%d px", pixels.size()); + count_label->label(buf); // обновляем надпись + + redraw(); + } + + int handle(int event) { + double x = Fl::event_x(); + double y = Fl::event_y(); + + if (x < CANVAS_X || x > CANVAS_X + CANVAS_WIDTH - 1 || y < CANVAS_Y || y > CANVAS_Y + CANVAS_HEIGHT - 1) // если мышка за границей холста, то ничего не делаем + return Fl_Window::handle(event); + + if (event == FL_PUSH) { + setpixel(round(x / GRID_LEN), round(y / GRID_LEN), Fl::event_button() == FL_LEFT_MOUSE); //округляем координаты исходя из зерна, добавляем или удаляем пиксель в зависимости от кнопки мыши + } + if (event == FL_DRAG) { + setpixel(round(x / GRID_LEN), round(y / GRID_LEN), Fl::event_button() == FL_LEFT_MOUSE); + } + + return Fl_Window::handle(event); + } + + void draw(void) { + Fl_Window::draw(); + fl_color(FL_WHITE); + fl_rectf(CANVAS_X, CANVAS_Y, CANVAS_WIDTH, CANVAS_HEIGHT); // заливаем белый квадрат + fl_color(FL_BLACK); + + typedef PointMap::iterator it_type; + for (it_type iterator = pixels.begin(); iterator != pixels.end(); iterator++) { // перебираем все пиксели + int x = iterator->second.x; + int y = iterator->second.y; + fl_rectf(x, y, 5, 5); // рисуем точки + } + } +}; + +PaintWindow *window; + +int main(void) { + window = new PaintWindow(200, 300, "Points"); //создаём окно + count_label = new Fl_Box(34, 177, 133, 56, "..."); // создаём подпись + count_label->labelsize(50); //выставляем размер шрифта + + window->end(); // закрываем группу окна + window->show(); // показываем окно + return Fl::run(); +} +``` + +Теперь нужно сие дело откомпилить. Открываем терминал в папке с программой и пишем там + +```cmd +g++ <имя_исходника> -o <имя_исполняемого_файла> -DWIN32 -D__NO_INLINE__ -static -static-libgcc -static-libstdc++ -lfltk -lmingw32 -lole32 -luuid -lcomctl32 -mwindows +``` + +**-DWIN32** – флаг, которые заставят думать FLTK, что мы под Windows + +**-mwindows** – убираем чёрное окошко у приложения и подключаем некоторые системные библиотеки + +**-DNO_INLINE** – флаг, который заставит работать math в нашей программе + +**-static -static-libgcc -static-libstdc++** – флаги. благодаря которым программа запустится на других компьютерах и не будет ничего требовать + +**-lfltk -lmingw32 -lole32 -luuid -lcomctl32** – флаги, с помощью которых подключается библиотека и всё, что ей требуется. В некоторых случаях может также понадобиться флаг -lgdi32. + +Также можно добавить флаги **-O2** и **-s** для уменьшения размера исполняемого файла. + +![output](output.png) + +Теперь можно запустить наше творение :) + +![app](app.png) + +И да, код программы ужасен и написан в исключительно демонстрационных целях. + +Источников в этот раз не будет, так как всю информацию черпал из программ-примеров, находящихся в том же архиве, что и исходник библиотеки (папки examples и test). + diff --git a/content/posts/fltk-apps/mingw1.png b/content/posts/fltk-apps/mingw1.png new file mode 100644 index 0000000..9bfe4f4 Binary files /dev/null and b/content/posts/fltk-apps/mingw1.png differ diff --git a/content/posts/fltk-apps/mingw2.png b/content/posts/fltk-apps/mingw2.png new file mode 100644 index 0000000..d703c19 Binary files /dev/null and b/content/posts/fltk-apps/mingw2.png differ diff --git a/content/posts/fltk-apps/mingw3.png b/content/posts/fltk-apps/mingw3.png new file mode 100644 index 0000000..cacd862 Binary files /dev/null and b/content/posts/fltk-apps/mingw3.png differ diff --git a/content/posts/fltk-apps/mingw4.png b/content/posts/fltk-apps/mingw4.png new file mode 100644 index 0000000..459c57c Binary files /dev/null and b/content/posts/fltk-apps/mingw4.png differ diff --git a/content/posts/fltk-apps/mingw5.png b/content/posts/fltk-apps/mingw5.png new file mode 100644 index 0000000..23984fb Binary files /dev/null and b/content/posts/fltk-apps/mingw5.png differ diff --git a/content/posts/fltk-apps/miniature.jpg b/content/posts/fltk-apps/miniature.jpg new file mode 100644 index 0000000..cc7478d Binary files /dev/null and b/content/posts/fltk-apps/miniature.jpg differ diff --git a/content/posts/fltk-apps/output.png b/content/posts/fltk-apps/output.png new file mode 100644 index 0000000..4de40ea Binary files /dev/null and b/content/posts/fltk-apps/output.png differ diff --git a/content/posts/fltk-apps/src.png b/content/posts/fltk-apps/src.png new file mode 100644 index 0000000..c25370c Binary files /dev/null and b/content/posts/fltk-apps/src.png differ diff --git a/content/posts/fox-toolkit-apps/app.png b/content/posts/fox-toolkit-apps/app.png new file mode 100644 index 0000000..fc082c8 Binary files /dev/null and b/content/posts/fox-toolkit-apps/app.png differ diff --git a/content/posts/fox-toolkit-apps/exe.png b/content/posts/fox-toolkit-apps/exe.png new file mode 100644 index 0000000..a15f94c Binary files /dev/null and b/content/posts/fox-toolkit-apps/exe.png differ diff --git a/content/posts/fox-toolkit-apps/index.md b/content/posts/fox-toolkit-apps/index.md new file mode 100644 index 0000000..486e453 --- /dev/null +++ b/content/posts/fox-toolkit-apps/index.md @@ -0,0 +1,277 @@ +--- +title: "Fox Toolkit - пишем маленькие кросс-платформенные приложения с более мощной библиотекой" +categories: ["cpp", "archive"] +date: 2015-08-21T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +После того, как мы [поиграли с FLTK](/fltk-apps), я нашёл ещё одну библиотеку виджетов - Fox Toolkit. Эта библиотека предоставляет более широкие возможности для разработки приложений с графическим интерфейсом. + +Библиотека также поставляется в виде исходного кода и скачивается с [официального сайта](http://www.fox-toolkit.org/download.html). В статье рассматривается версия 1.6.50. Компилируем под Windows. + + + +Все шаги до компиляции аналогичны шагам в [предыдущей статье](/fltk-apps). Открываем документик по пути `куда_распаковали\doc\win32.html` и листаем в самый низ. Ух ты, всё так просто. + +Только не компилируется нихрена. + +Оказывается, не один я столкнулся с этой проблемой, так что гугл помог. Вот [тема на форуме](https://forum.fox-toolkit.org/index.php?topic=34.0), которая мне помогла. + +Итак, что нужно сделать: + +1. Запустить `./configure --without-x --without-xft` вместо `./configure` + +2. Исправить заголовочный файл `куда_распаковали\include\xincs.h`: + +```cpp +#ifdef HAVE_GL_H // (240 строка) +#ifndef SUN_OGL_NO_VERTEX_MACROS +#define SUN_OGL_NO_VERTEX_MACROS +#endif +#ifndef HPOGL_SUPPRESS_FAST_API +#define HPOGL_SUPPRESS_FAST_API +#endif #include +#ifndef WIN32 // ifndef заменить на ifdef +#include // GL/glx.h заменить на GL/glext.h +#endif // (250 строка) +``` + +Всё, теперь запускаем **make**, а потом **make install.** Затем можно забирать результат из `туда_куда_установлен_MinGw\msys\1.0\local`. + +На этом с компиляцией всё. + +# Пишем программу + +В качестве примера снова будем писать программу, которая будет считать количество нарисованных пикселей. Почему бы и нет? Используем разметку, которую мы нарисовали в предыдущей статье. + +fox_test.cpp: +```cpp +#include "fox-1.6/fx.h" +#include + +char buf[16]; + +struct point { + int x, y; +}; + +#define CANVAS_X 10 +#define CANVAS_Y 10 +#define CANVAS_WIDTH 180 +#define CANVAS_HEIGHT 100 +#define GRID_LEN 5 // размер зерна в холсте + +class PaintWindow : public FXMainWindow { +FXDECLARE(PaintWindow) + + typedef std::map, point> PointMap; + + +private: + FXCanvas *canvas; // холст, на котором будем рисовать + FXLabel *count_label; // надпись + FXFont *big_font; // шрифт для надписи + int isMouseDown; + FXColor drawColor; // цвет пикселей на холсте + FXColor bgColor; // цвет фона холста + PointMap pixels; // карта с координатами пикселей + void setpixel(FXEvent *event); + +protected: + PaintWindow() { } + +public: + + enum { // ID обработчиков событий + ID_CANVAS = FXMainWindow::ID_LAST, + }; + + long onPaint(FXObject *, FXSelector, void *); + + long onMouseDown(FXObject *, FXSelector, void *); + + long onMouseUp(FXObject *, FXSelector, void *); + + long onMouseMove(FXObject *, FXSelector, void *); + + PaintWindow(FXApp *a); + + virtual void create(); + + virtual ~PaintWindow(); + +}; + +FXDEFMAP(PaintWindow) PaintWindowMap[] = { // определяем обработчики событий + FXMAPFUNC(SEL_PAINT, PaintWindow::ID_CANVAS, PaintWindow::onPaint), + FXMAPFUNC(SEL_LEFTBUTTONPRESS, PaintWindow::ID_CANVAS, PaintWindow::onMouseDown), + FXMAPFUNC(SEL_RIGHTBUTTONPRESS, PaintWindow::ID_CANVAS, PaintWindow::onMouseDown), + FXMAPFUNC(SEL_LEFTBUTTONRELEASE, PaintWindow::ID_CANVAS, PaintWindow::onMouseUp), + FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, PaintWindow::ID_CANVAS, PaintWindow::onMouseUp), + FXMAPFUNC(SEL_MOTION, PaintWindow::ID_CANVAS, PaintWindow::onMouseMove) +}; + +FXIMPLEMENT(PaintWindow, FXMainWindow, PaintWindowMap, ARRAYNUMBER(PaintWindowMap)) + + +PaintWindow::PaintWindow(FXApp *a) : FXMainWindow(a, a->getAppName(), NULL, NULL, + DECOR_TITLE | DECOR_BORDER | DECOR_MINIMIZE | + DECOR_CLOSE, //настраиваем вид окна + 0, 0, 200, 300) { //выставляем размер окна + + canvas = new FXCanvas(this, this, ID_CANVAS, FRAME_SUNKEN | FRAME_THICK | LAYOUT_EXPLICIT, + CANVAS_X, + CANVAS_Y, + CANVAS_WIDTH, + CANVAS_HEIGHT); // задаём параметры холста, LAYOUT_EXPLICIT - абсолютное позиционирование + + count_label = new FXLabel(this, "...", NULL, LAYOUT_EXPLICIT, 34, 177, 133, 56); + + FXFontDesc fontdescription; + getApp()->getNormalFont()->getFontDesc(fontdescription); // получаем стандартный шрифт + + big_font = new FXFont(getApp(), fontdescription.face, 37, + FXFont::Normal); // создаём стандартный шрифт с нужным размером + big_font->create(); + + count_label->setFont(big_font); + + drawColor = FXRGB(0, 0, 0); + bgColor = FXRGB(255, 255, 255); + + isMouseDown = 0; +} + + +PaintWindow::~PaintWindow() { + +} + + +void PaintWindow::create() { + FXMainWindow::create(); + show(PLACEMENT_SCREEN); //показываем окно в центре экрана +} + +void PaintWindow::setpixel(FXEvent *event) { + int x = event->win_x; + int y = event->win_y; + + if (x < 0 || y < 0 || x + 2 >= CANVAS_WIDTH || y + 2 >= CANVAS_HEIGHT) + return; // проверяем, не вышел ли курсор за пределы холста + + x = (event->win_x + 2) / GRID_LEN; + y = (event->win_y + 2) / GRID_LEN; + + std::pair p = std::make_pair(x * GRID_LEN, y * GRID_LEN); // создаём хеш из двух координат + + FXDCWindow dc(canvas); + + bool add = event->click_button == 1; // если кнопка левая, то рисуем, правой - удаляем + + dc.setForeground(add ? drawColor : bgColor); + + if (add) { + point pixel; + pixel.x = x * GRID_LEN; + pixel.y = y * GRID_LEN; + pixels[p] = pixel; + } else { + pixels.erase(p); + } + + dc.fillRectangle(x * GRID_LEN, y * GRID_LEN, GRID_LEN, GRID_LEN); // рисуем квадратики + + sprintf(buf, "%d px", pixels.size()); + count_label->setText(buf); // обновляем надпись +} + +long PaintWindow::onMouseUp(FXObject *, FXSelector, void *ptr) { // при отпускании мыши + canvas->ungrab(); // отключаем перетаскивание в холсте + if (isMouseDown) { + FXDCWindow dc(canvas); + dc.setForeground(drawColor); + isMouseDown = 0; + } + return 1; +} + +long PaintWindow::onMouseDown(FXObject *, FXSelector, void *ptr) { // при нажатии мыши + canvas->grab(); // включаем перетаскивание в холсте + setpixel((FXEvent *) ptr); + isMouseDown = 1; + return 1; +} + + +long PaintWindow::onMouseMove(FXObject *, FXSelector, void *ptr) { + if (isMouseDown) { + setpixel((FXEvent *) ptr); + } + return 1; +} + + +long PaintWindow::onPaint(FXObject *, FXSelector, + void *ptr) { //если окно сворачивается или выходит за пределы видимости, то его нужно перерисовать + FXEvent *ev = (FXEvent *) ptr; + FXDCWindow dc(canvas, ev); + dc.setForeground(bgColor); + dc.fillRectangle(ev->rect.x, ev->rect.y, ev->rect.w, ev->rect.h); + + typedef PointMap::iterator it_type; + for (it_type iterator = pixels.begin(); + iterator != pixels.end(); iterator++) { // перебираем все пиксели наносим их на холст + int x = iterator->second.x; + int y = iterator->second.y; + dc.setForeground(drawColor); + dc.fillRectangle(x, y, GRID_LEN, GRID_LEN); + + } + return 1; +} + +int main(int argc, char **argv) { + FXApp application("Pixels", "MultiMote"); + application.init(argc, argv); + + new PaintWindow(&application); + application.create(); + + return application.run(); +} +``` + +##### Компилируем исходник следующей командой: + +```cmd +g++ имя_исходника -o имя_результата -static -static-libgcc -static-libstdc++ -lFOX-1.6 -mwindows +``` + +**-static -static-libgcc -static-libstdc++** – связываем библиотеки MinGw с приложением, чтобы оно запускалось на других компьютерах + +**-lFOX-1.6** – подключаем библиотеку + +**-mwindows** – убираем окно команд и подключаем несколько системных приложений + +Также можно добавить флаги **-O2** и **-s** для уменьшения размера исполняемого файла. + +![|580](exe.png) + +Теперь можно запускать: + +![|206](app.png) + +Под linux приложение выглядит точно так же: + +![|659](linux.png) + +Цель достигнута :) + +Итак, можно делать выводы. + +Библиотека предоставляет гораздо большие возможности, чем FLTK. + +А если честно, библиотека меня крайне выбесила. \ No newline at end of file diff --git a/content/posts/fox-toolkit-apps/linux.png b/content/posts/fox-toolkit-apps/linux.png new file mode 100644 index 0000000..0ca2655 Binary files /dev/null and b/content/posts/fox-toolkit-apps/linux.png differ diff --git a/content/posts/fox-toolkit-apps/miniature.jpg b/content/posts/fox-toolkit-apps/miniature.jpg new file mode 100644 index 0000000..a3fda1b Binary files /dev/null and b/content/posts/fox-toolkit-apps/miniature.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/18038a.jpg b/content/posts/nokia5110-lcd-connection/18038a.jpg new file mode 100644 index 0000000..32b1b23 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/18038a.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/3310_proteus.zip b/content/posts/nokia5110-lcd-connection/3310_proteus.zip new file mode 100644 index 0000000..3f60761 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/3310_proteus.zip differ diff --git a/content/posts/nokia5110-lcd-connection/5110cut.jpg b/content/posts/nokia5110-lcd-connection/5110cut.jpg new file mode 100644 index 0000000..5fe0e03 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/5110cut.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/5110lcd_wire.jpg b/content/posts/nokia5110-lcd-connection/5110lcd_wire.jpg new file mode 100644 index 0000000..6da2ddf Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/5110lcd_wire.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/5110phone.jpg b/content/posts/nokia5110-lcd-connection/5110phone.jpg new file mode 100644 index 0000000..7b2cf7f Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/5110phone.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/5110phone_inside.jpg b/content/posts/nokia5110-lcd-connection/5110phone_inside.jpg new file mode 100644 index 0000000..02366a6 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/5110phone_inside.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/index.md b/content/posts/nokia5110-lcd-connection/index.md new file mode 100644 index 0000000..ec301d3 --- /dev/null +++ b/content/posts/nokia5110-lcd-connection/index.md @@ -0,0 +1,84 @@ +--- +title: "Подключение дисплея от nokia 5110/3310 к AVR" +categories: ["mcu", "archive"] +date: 2015-08-13T00:00:00+03:00 +draft: false +featured_image: lcd_image4.jpg +--- + + +Итак, наконец-то повезло приобрести телефон nokia 5110. В телефоне много разных вкусностей, но нас интересует дисплей. + + + +> :warning: Если вы используете AVR-GCC / WinAvr, то вам нужна +> [эта библиотека](https://github.com/gresolio/N3310Lib). +> Настоятельно рекомендую изучить [эту статью](../avr-lcd-images). + +![Телефон, собственно|300](5110phone.jpg) + +Разбираем телефон и добираемся до дисплея. + +![|300](5110phone_inside.jpg) + +Дисплей с печаткой соединяется резиновым шлейфом. Также под дисплеем располагаются светодиоды. Лучше всего отпилить часть печатки с дисплеем и припаять шлейф с коннектором, как я и поступил. + +![|300](5110cut.jpg) ![|300](5110lcd_wire.jpg) + +На плате с дисплеем я напаял несколько перемычек, дабы уменьшить количество проводов.![Распиновка дисплея|300](lph7366_pinout.png) + +![Распиновка на печатке, вид сверху|500](lcd.png) + +Далее дисплей подключается к микроконтроллеру по такой схеме: + +![Подключение к МК|300](lcd_atmega8.png) + +Я использовал ATmega8, но подойдут и многие другие микроконтроллеры семейства AVR. Пины можно изменить в программе. Схему я питал напряжением 3.3в, но для питания от пяти нужно сделать коммутацию на резисторах. Драйвер собран из нескольких источников. Код для CodeVisionAvr. Русские буквы в набор входят :) + +Функции приведены ниже + +```cpp +void lcd_init(void); //инициализация дисплея +void lcd_contrast(unsigned char contrast); //установить контраст +void lcd_clear(void); //очистить диплей +void lcd_clear_area(unsigned int line, unsigned char startX, unsigned char endX); //очистить поле +void lcd_clear_line(unsigned int line); //очистить линию +void lcd_gotoxy(unsigned int x, unsigned int y); //переместить курсов в заданную позицию +void lcd_putch(char chr); //вывод символа +void lcd_str(char *str); //вывод строки +void lcd_image( flash unsigned char img[]); //вывод изображения из программы Image generate +void lcd_extrachar(int num); //вывод дополнительных символов (пока только значок заряда, 7x10) +``` + +Пины меняются в заголовочном файле lcd.h + +```cpp +#define LCD_CLK_PIN PORTB.0 +#define LCD_DATA_PIN PORTB.1 +#define LCD_DC_PIN PORTB.2 +#define LCD_RST_PIN PORTB.3 +``` + +Стоит напомнить, что префикс **flash** перед переменной означает, что она сохраняется не в оперативной памяти, а во **flash** памяти МК. Использовал по причине нехватки памяти при хранении изображений. + +Ну и демонстрация работы + +![|300](lcd_image1.jpg) ![|300](lcd_image2.jpg) + +![|300](lcd_image3.jpg) ![|300](lcd_image4.jpg) + +**Ссылки:** + +[Архив с исходником](nokia5510.zip) + +[Модель для Proteus](3310_proteus.zip) + +[Тут я нашёл распиновку](http://serdisplib.sourceforge.net/ser/pcd8544.html) + +[Программа Image Generate](http://alex-exe.ru/programm/image-generate/) + +[Программа GLCD Font Creator](http://www.mikroe.com/glcd-font-creator) + +Прочие источники: +[раз](http://we.easyelectronics.ru/lcd_gfx/biblioteka-dlya-raboty-s-displeem-nokia-3310.html), +[два](http://pro-radio.ru/controllers/5210/) \ No newline at end of file diff --git a/content/posts/nokia5110-lcd-connection/lcd.png b/content/posts/nokia5110-lcd-connection/lcd.png new file mode 100644 index 0000000..c0f3be9 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/lcd.png differ diff --git a/content/posts/nokia5110-lcd-connection/lcd_atmega8.png b/content/posts/nokia5110-lcd-connection/lcd_atmega8.png new file mode 100644 index 0000000..a407714 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/lcd_atmega8.png differ diff --git a/content/posts/nokia5110-lcd-connection/lcd_image1.jpg b/content/posts/nokia5110-lcd-connection/lcd_image1.jpg new file mode 100644 index 0000000..e89fd6c Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/lcd_image1.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/lcd_image2.jpg b/content/posts/nokia5110-lcd-connection/lcd_image2.jpg new file mode 100644 index 0000000..7b8ff8b Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/lcd_image2.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/lcd_image3.jpg b/content/posts/nokia5110-lcd-connection/lcd_image3.jpg new file mode 100644 index 0000000..bcb8471 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/lcd_image3.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/lcd_image4.jpg b/content/posts/nokia5110-lcd-connection/lcd_image4.jpg new file mode 100644 index 0000000..0d599e3 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/lcd_image4.jpg differ diff --git a/content/posts/nokia5110-lcd-connection/lph7366_pinout.png b/content/posts/nokia5110-lcd-connection/lph7366_pinout.png new file mode 100644 index 0000000..f7ca267 Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/lph7366_pinout.png differ diff --git a/content/posts/nokia5110-lcd-connection/main.py b/content/posts/nokia5110-lcd-connection/main.py new file mode 100644 index 0000000..20eb129 --- /dev/null +++ b/content/posts/nokia5110-lcd-connection/main.py @@ -0,0 +1,133 @@ +import zipfile +import io +import os +import time +from flask_executor import Executor +import uuid + +from flask import Flask, render_template, jsonify, redirect, request, send_file, flash +from flask_login import login_user, logout_user, LoginManager, UserMixin +from flask_sessionstore import Session +from werkzeug.security import check_password_hash, generate_password_hash +from werkzeug.utils import secure_filename + + + +app = Flask(__name__) +app.secret_key = b'4554bvcj34k34 kl43 n4 v43nlk34nkv5nm34v535' +app.config['SESSION_TYPE'] = 'filesystem' +app.config['SESSION_FILE_DIR'] = 'tmp/sessions' + +admins = { + # {"username" : "bobby", "password": "40bd001563085fc35165329ea1ff5c5ecbdbbeef"} #sha1 + # {"username" : "bobby", "password": "$2y$12$11VQXE/ouspmtf/9U02BAuRNHwTi0Qzd.HUn4Oh.uEgDKi8vP.Lw2"} #bcrypt + "bobby": { + "password_hash": "pbkdf2:sha256:150000$GkUZvh2C$5cf29b24cb7ec99e44984b6f6cf739fd7fd01ff27e84bc08e72291d0532410e1" + } +} + + + +session_store = Session() +session_store.init_app(app) + +login_manager = LoginManager() +login_manager.init_app(app) + +pool = Executor(app) + +class AdminUser(UserMixin): + def __init__(self, user_id): + self.id = user_id + + +def worker_done(future): + print("done") + +pool.add_default_done_callback(worker_done) + +def worker(): + for i in range(1, 5): + print("working") + time.sleep(1) + # print("finished") + +@app.route("/work") +def work(): + id = uuid.uuid1() + print("new job: %s" % id) + pool.submit_stored(id, worker) + return redirect('/') + + +@login_manager.user_loader +def load_user(user_id): + if user_id in admins: + return AdminUser(user_id) + return None + +@app.route("/", methods=['GET', 'POST']) +def index(): + if request.method == 'POST': + files = request.files.getlist("up[]") + for f in files: + if f.filename: + filename = secure_filename(f.filename) + f.save(os.path.join(app.root_path, "tmp", filename)) + + done = False + + if pool.futures.done('worker1'): + pool.futures.pop('worker1') + done = True + + return render_template("index.jinja", thread_done=done) + + +@app.route("/zip") +def zipf(): + # membytes = io.BytesIO() + membytes = io.BytesIO() + zip_obj = zipfile.ZipFile(membytes, "w") + zip_obj.writestr("a.txt", "hello, world") + zip_obj.close() + + membytes.seek(0) + return send_file(membytes, mimetype='application/zip', as_attachment=True, attachment_filename="zip.zip") + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + username = request.form.get('username') + password = request.form.get('password') + if username in admins: + userdata = admins[username] + if check_password_hash(userdata["password_hash"], password): + u = AdminUser(username) + login_user(u) + return redirect('/') + else: + print("wrong password") + else: + print("user not found") + + return redirect('/login') + else: + return render_template("login.jinja") + # u = AdminUser("bobby") + # login_user(u) + return redirect('/') + + +@app.route("/logout") +def logout(): + logout_user() + return redirect('/') + +@app.route("/api", methods=['GET']) +def api(): + j = { + "username": "Bobby" + } + return jsonify(j) + diff --git a/content/posts/nokia5110-lcd-connection/nokia5510.zip b/content/posts/nokia5110-lcd-connection/nokia5510.zip new file mode 100644 index 0000000..a5fb6ad Binary files /dev/null and b/content/posts/nokia5110-lcd-connection/nokia5510.zip differ diff --git a/content/posts/nrf-dualshock/index.md b/content/posts/nrf-dualshock/index.md new file mode 100644 index 0000000..0d2c415 --- /dev/null +++ b/content/posts/nrf-dualshock/index.md @@ -0,0 +1,1012 @@ +--- +title: "nRF24L01 + DualShock2 = радиоуправление" +categories: ["mcu", "archive"] +date: 2016-01-28T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Я, наконец-то решился купить модули nRF24L01. Для знакомства с ними нужно придумать что из них сделать. +И сделал радиоуправляемую машинку. Из всего, что есть. + +Наверное, все в детстве хотели радиоуправляемую машинку :) + + + +Выглядят модули вот так: + +![Радиомодуль nRF24L01](nrf24l01.jpg "Радиомодуль nRF24L01") + +Описание: + +Дальность до 100 м. +Скорость до 2 Мб +Интерфейс SPI для управления +Напряжение: 3-3.6В (рекомендуется 3,3) В +Максимальная выходная мощность: +20 дБм +Коэффициент усиления антенны (пиковая): 2dBi + +Работает радиомодуль на частоте 2.4ГГц (как эти ваши вайфаи и блютузы). + +В качестве пульта я решил использовать тот самый [белый геймпад](/dualshock-avr-usb) (он не обиделся). Нормальных библиотек особо не нашёл, почитал [мануал](http://store.curiousinventor.com/guides/ps2), посмотрел структуру пакета (рисунок 2), решил написать сам. Геймпад общается по протоколу SPI. + +![Структура пакета геймпада](psx_packet.png "Структура пакета геймпада") + +Вроде бы ничего сложного, написал. Подключил экран и проверил. Работает: + + + +И всё работало замечательно пока не отключили свет. И так повезло, что после этого все исходники превратились в кровавое месиво. И тут я случайно нашёл другую [библиотеку](http://digitalcave.ca/resources/avr/psx.jsp) и взял ее. + +После обработки напильником библиотека стала иметь более-менее приличный вид: + +psx.h: +```c +#ifndef PSX_lib_h +#define PSX_lib_h + +#include +#include + + +#define PSX_DATA_PORT PORTD +#define PSX_SCK_PORT PORTD +#define PSX_DC_PORT PORTD +#define PSX_CS_PORT PORTD + +#define PSX_DATA_PINREG PIND + +#define PSX_DATA_DDR DDRD +#define PSX_SCK_DDR DDRD +#define PSX_DC_DDR DDRD +#define PSX_CS_DDR DDRD + +#define PSX_SCK_PIN 4 +#define PSX_DC_PIN 7 +#define PSX_CS_PIN 5 +#define PSX_DATA_PIN 6 + +// задержка тактов SPI, us +#define CTRL_CLK 10 + +// кнопкм +#define PSB_SELECT 0x0001 +#define PSB_L3 0x0002 +#define PSB_R3 0x0004 +#define PSB_START 0x0008 +#define PSB_PAD_UP 0x0010 +#define PSB_PAD_RIGHT 0x0020 +#define PSB_PAD_DOWN 0x0040 +#define PSB_PAD_LEFT 0x0080 +#define PSB_L2 0x0100 +#define PSB_R2 0x0200 +#define PSB_L1 0x0400 +#define PSB_R1 0x0800 +#define PSB_TRIANGLE 0x1000 +#define PSB_CIRCLE 0x2000 +#define PSB_CROSS 0x4000 +#define PSB_SQUARE 0x8000 + +// джойстики +#define PSS_RX 5 +#define PSS_RY 6 +#define PSS_LX 7 +#define PSS_LY 8 + + +// инициализация геймпада +void psx_init(bool analog); + +// получить состояние всех кнопок +uint16_t psx_buttons(); + +// получить состояниие кнопки (PSB_x) +uint8_t psx_button(uint16_t); + +// получить состояниие оси джойстика (PSS_x) +uint8_t psx_stick(unsigned int); + +// обновить состояние кнопок +void psx_read_gamepad(); + +#endif +``` + +psx.c: +```c +#include "psx.h" +#include + +// буфер +static uint8_t _psx_data[21]; + +// отправить байт программным SPI и получить ответ +uint8_t _psx_gamepad_shift(uint8_t transmit_byte) { + uint8_t received_byte = 0; + for(uint8_t i = 0; i < 8; i++) { + PSX_SCK_PORT &= ~_BV(PSX_SCK_PIN); + + if (transmit_byte & (_BV(i))) { + PSX_DC_PORT |= _BV(PSX_DC_PIN); + } + else { + PSX_DC_PORT &= ~_BV(PSX_DC_PIN); + } + + _delay_us(CTRL_CLK); + + PSX_SCK_PORT |= _BV(PSX_SCK_PIN); + + if(PSX_DATA_PINREG & _BV(PSX_DATA_PIN)) { + received_byte |= _BV(i); + } + + _delay_us(CTRL_CLK); + } + + PSX_SCK_PORT |= _BV(PSX_SCK_PIN); + + return received_byte; +} + +// отправить команду +void _psx_send_command(uint8_t send_data[], uint8_t size){ + PSX_CS_PORT &= ~(_BV(PSX_CS_PIN)); + PSX_DC_PORT |= _BV(PSX_DC_PIN); + + PSX_SCK_PORT |= _BV(PSX_SCK_PIN); + + for (uint8_t i = 0; i < size; i++){ + send_data[i] = _psx_gamepad_shift(send_data[i]); + } + + PSX_CS_PORT |= _BV(PSX_CS_PIN); +} + +// обновить состояние кнопок +void psx_read_gamepad() { + _psx_data[0] = 0x01; + _psx_data[1] = 0x42; + for (uint8_t i = 2; i < 21; i++){ + _psx_data[i] = 0x00; + } + _psx_send_command(_psx_data, 21); +} + +// инициализация геймпада +void psx_init(bool analog){ + + PSX_SCK_DDR |= _BV(PSX_SCK_PIN); + PSX_CS_DDR |= _BV(PSX_CS_PIN); + PSX_DC_DDR |= _BV(PSX_DC_PIN); + + PSX_DATA_DDR &= ~(_BV(PSX_DATA_PIN)); + PSX_DATA_PORT |= _BV(PSX_DATA_PIN); + + PSX_SCK_PORT |= _BV(PSX_SCK_PIN); + PSX_DC_PORT |= _BV(PSX_DC_PIN); + + psx_read_gamepad(); + + if(!analog) return; + + // войти в режим конфигурации + uint8_t enter_config_command[] = {0x01, 0x43, 0x00, 0x01, 0x00}; + _psx_send_command(enter_config_command, 5); + + // заблокирвать геймпад в аналоговом режиме + uint8_t lock_analog_mode_command[] = {0x01, 0x44, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}; + _psx_send_command(lock_analog_mode_command, 9); + + // выйти из режима конфигурации + uint8_t exit_config_command[] = {0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A}; + _psx_send_command(exit_config_command, 9); +} + +// получить состояние всех кнопок +uint16_t psx_buttons() { + uint16_t buttons = *(uint16_t*)(_psx_data + 3); // получить 2 байта, содержащих позиции данных 3 и 4 + return ~buttons; +} + +// получить состояниие кнопки (PSB_x +uint8_t psx_button(uint16_t button) { + uint16_t buttons = psx_buttons(); + return ((buttons & button) > 0); +} + +// получить состояниие оси джойстика (PSS_x) +uint8_t psx_stick(unsigned int stick) { + return _psx_data[stick]; +} +``` + + + +Код передатчика: + +host.c: +```c +#define NRF24_IO_PORT PORTC +#define NRF24_IO_PINREG PINC +#define NRF24_IO_DDR DDRC + +#include +#include +#include "lib/nrf24.h" +#include "lib/psx.h" + +// ATMega8 nrf24 +// ________ _________ +// | PC0 |----| CE | +// | PC1 |----| CSN | +// | PC2 |----| SCK | +// | PC3 |----| MOSI | +// | PC4 |----| MISO | +// | | |_________| +// | | +// | | Геймпад +// | | _________ +// | PD4 |----| SCK | +// | PD5 |----| CS | +// | PD6 |----| DATA | +// | PD7 |----| DC | +// |________| |_________| + + +uint8_t data_array[2]; +uint8_t tx_address[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; +uint8_t rx_address[5] = {0xD7, 0xD7, 0xD7, 0xD7, 0xD7}; + + +int main() { + + nrf24_init(); + + nrf24_config(2, 2); // канал 2, размер пакета 2 + + nrf24_tx_address(tx_address); + nrf24_rx_address(rx_address); + + psx_init(false); + + while (1) { + + psx_read_gamepad(); // чтение геймпада + + data_array[0] = 0xFE; // проверочное значение + + // вверх - левое шасси вперёд + // вниз - левое шасси назад + // треугольник - правое шасси вперёд + // крест - правое шасси назад + data_array[1] = (psx_button(PSB_PAD_UP) << 1) | (psx_button(PSB_PAD_DOWN) << 2) + | (psx_button(PSB_TRIANGLE) << 3) | (psx_button(PSB_CROSS) << 4); // запихиваем кнопки + + nrf24_send(data_array); // отправляем данные + while (!nrf24_isSending()); + + _delay_ms(20); + + } +} +``` + +Код черепахи: + +turtle.c: +```c +#include +#include "lib/nrf24.h" +#include +#include + +// ATMega8 nrf24 +// ________ _________ +// | PC0 |----| CE | +// | PC1 |----| CSN | +// | PC2 |----| SCK | +// | PC3 |----| MOSI | +// | PC4 |----| MISO | +// | | |_________| +// | | +// | | Шасси +// | PD0 |-(2) (1)--[/\ /\]--(3) +// | PD1 |-(1) |L| |R| +// | PD2 |-(3) |L| |R| +// | PD3 |-(4) (2)--[\/ \/]--(4) +// |________| + +uint8_t data_array[2]; +uint8_t tx_address[5] = {0xD7, 0xD7, 0xD7, 0xD7, 0xD7}; +uint8_t rx_address[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; + +#define ENGINES_PORT PORTD +#define ENGINES_DDR DDRD + +#define LEFT_CHASSIS_FWD_PIN 1 +#define LEFT_CHASSIS_REV_PIN 0 + +#define RIGHT_CHASSIS_FWD_PIN 3 +#define RIGHT_CHASSIS_REV_PIN 2 + +int main() { + + ENGINES_DDR |= 0b00001111; + nrf24_init(); + + nrf24_config(2, 2); // канал 2, размер пакета 2 + + nrf24_tx_address(tx_address); + nrf24_rx_address(rx_address); + + + while (1) { + + if (nrf24_dataReady()) nrf24_getData(data_array); + + if (data_array[0] == 0xFE) { // проверка типа пакета + bool left_fw = (data_array[1] & (1 << 1)) != 0; + bool left_bck = (data_array[1] & (1 << 2)) != 0; + bool right_fw = (data_array[1] & (1 << 3)) != 0; + bool right_bck = (data_array[1] & (1 << 4)) != 0; + ENGINES_PORT = (left_fw << LEFT_CHASSIS_FWD_PIN) | (right_fw << RIGHT_CHASSIS_FWD_PIN) | + (left_bck << LEFT_CHASSIS_REV_PIN) | (right_bck << RIGHT_CHASSIS_REV_PIN); + } + + _delay_ms(20); + + } +} +/* ------------------------------------------------------------------------- */ +``` + +Библиоткека для nRF24: + +nrf24.h: +```c +/* +* ---------------------------------------------------------------------------- +* “THE COFFEEWARE LICENSE” (Revision 1): +* wrote this file. As long as you retain this notice you +* can do whatever you want with this stuff. If we meet some day, and you think +* this stuff is worth it, you can buy me a coffee in return. +* ----------------------------------------------------------------------------- +* This library is based on this library: +* https://github.com/aaronds/arduino-nrf24l01 +* Which is based on this library: +* http://www.tinkerer.eu/AVRLib/nRF24L01 +* ----------------------------------------------------------------------------- +*/ +#ifndef NRF24 +#define NRF24 + +#include +#include + +#ifdef TURTLE +#define NRF24_IO_PORT PORTB +#define NRF24_IO_PINREG PINB +#define NRF24_IO_DDR DDRB +#else +#define NRF24_IO_PORT PORTC +#define NRF24_IO_PINREG PINC +#define NRF24_IO_DDR DDRC +#endif + + +#define NRF24_CE_PIN 0 +#define NRF24_CSN_PIN 1 +#define NRF24_SCK_PIN 2 +#define NRF24_MOSI_PIN 3 +#define NRF24_MISO_PIN 4 + + +/* IO Helpers */ +#define nrf24_set_bit(reg,bit) reg |= (1< Pin HIGH + * - state:0 => Pin LOW */ +/* -------------------------------------------------------------------------- */ +extern void nrf24_ce_digitalWrite(uint8_t state); + +/* -------------------------------------------------------------------------- */ +/* nrf24 CE pin control function + * - state:1 => Pin HIGH + * - state:0 => Pin LOW */ +/* -------------------------------------------------------------------------- */ +extern void nrf24_csn_digitalWrite(uint8_t state); + +/* -------------------------------------------------------------------------- */ +/* nrf24 SCK pin control function + * - state:1 => Pin HIGH + * - state:0 => Pin LOW */ +/* -------------------------------------------------------------------------- */ +extern void nrf24_sck_digitalWrite(uint8_t state); + +/* -------------------------------------------------------------------------- */ +/* nrf24 MOSI pin control function + * - state:1 => Pin HIGH + * - state:0 => Pin LOW */ +/* -------------------------------------------------------------------------- */ +extern void nrf24_mosi_digitalWrite(uint8_t state); + +/* -------------------------------------------------------------------------- */ +/* nrf24 MISO pin read function +/* - returns: Non-zero if the pin is high */ +/* -------------------------------------------------------------------------- */ +extern uint8_t nrf24_miso_digitalRead(); + +#endif +``` + +nrf24.c: +```c +/* +* ---------------------------------------------------------------------------- +* “THE COFFEEWARE LICENSE” (Revision 1): +* wrote this file. As long as you retain this notice you +* can do whatever you want with this stuff. If we meet some day, and you think +* this stuff is worth it, you can buy me a coffee in return. +* ----------------------------------------------------------------------------- +* This library is based on this library: +* https://github.com/aaronds/arduino-nrf24l01 +* Which is based on this library: +* http://www.tinkerer.eu/AVRLib/nRF24L01 +* ----------------------------------------------------------------------------- +*/ +#include "nrf24.h" + +uint8_t payload_len; + +void nrf24_setupPins() { + nrf24_set_bit(NRF24_IO_DDR, NRF24_CE_PIN); // CE output + nrf24_set_bit(NRF24_IO_DDR, NRF24_CSN_PIN); // CSN output + nrf24_set_bit(NRF24_IO_DDR, NRF24_SCK_PIN); // SCK output + nrf24_set_bit(NRF24_IO_DDR, NRF24_MOSI_PIN); // MOSI output + nrf24_clr_bit(NRF24_IO_DDR, NRF24_MISO_PIN); // MISO input +} + +void nrf24_ce_digitalWrite(uint8_t state) { + if (state) { + nrf24_set_bit(NRF24_IO_PORT, NRF24_CE_PIN); + } + else { + nrf24_clr_bit(NRF24_IO_PORT, NRF24_CE_PIN); + } +} + +void nrf24_csn_digitalWrite(uint8_t state) { + if (state) { + nrf24_set_bit(NRF24_IO_PORT, NRF24_CSN_PIN); + } + else { + nrf24_clr_bit(NRF24_IO_PORT, NRF24_CSN_PIN); + } +} + + +void nrf24_sck_digitalWrite(uint8_t state) { + if (state) { + nrf24_set_bit(NRF24_IO_PORT, NRF24_SCK_PIN); + } + else { + nrf24_clr_bit(NRF24_IO_PORT, NRF24_SCK_PIN); + } +} + +void nrf24_mosi_digitalWrite(uint8_t state) { + if (state) { + nrf24_set_bit(NRF24_IO_PORT, NRF24_MOSI_PIN); + } + else { + nrf24_clr_bit(NRF24_IO_PORT, NRF24_MOSI_PIN); + } +} + +uint8_t nrf24_miso_digitalRead() { + return nrf24_check_bit(NRF24_IO_PINREG, NRF24_MISO_PIN); +} + + +/* init the hardware pins */ +void nrf24_init() { + nrf24_setupPins(); + nrf24_ce_digitalWrite(LOW); + nrf24_csn_digitalWrite(HIGH); +} + +/* configure the module */ +void nrf24_config(uint8_t channel, uint8_t pay_length) { + /* Use static payload length ... */ + payload_len = pay_length; + + // Set RF channel + nrf24_configRegister(RF_CH, channel); + + // Set length of incoming payload + nrf24_configRegister(RX_PW_P0, 0x00); // Auto-ACK pipe ... + nrf24_configRegister(RX_PW_P1, payload_len); // Data payload pipe + nrf24_configRegister(RX_PW_P2, 0x00); // Pipe not used + nrf24_configRegister(RX_PW_P3, 0x00); // Pipe not used + nrf24_configRegister(RX_PW_P4, 0x00); // Pipe not used + nrf24_configRegister(RX_PW_P5, 0x00); // Pipe not used + + // 1 Mbps, TX gain: 0dbm + nrf24_configRegister(RF_SETUP, (0 << RF_DR) | ((0x03) << RF_PWR)); + + // CRC enable, 1 byte CRC length + nrf24_configRegister(CONFIG, nrf24_CONFIG); + + // Auto Acknowledgment + nrf24_configRegister(EN_AA, (1 << ENAA_P0) | (1 << ENAA_P1) | (0 << ENAA_P2) | (0 << ENAA_P3) | (0 << ENAA_P4) | + (0 << ENAA_P5)); + + // Enable RX addresses + nrf24_configRegister(EN_RXADDR, + (1 << ERX_P0) | (1 << ERX_P1) | (0 << ERX_P2) | (0 << ERX_P3) | (0 << ERX_P4) | (0 << ERX_P5)); + + // Auto retransmit delay: 1000 us and Up to 15 retransmit trials + nrf24_configRegister(SETUP_RETR, (0x04 << ARD) | (0x0F << ARC)); + + // Dynamic length configurations: No dynamic length + nrf24_configRegister(DYNPD, + (0 << DPL_P0) | (0 << DPL_P1) | (0 << DPL_P2) | (0 << DPL_P3) | (0 << DPL_P4) | (0 << DPL_P5)); + + // Start listening + nrf24_powerUpRx(); +} + +/* Set the RX address */ +void nrf24_rx_address(uint8_t *adr) { + nrf24_ce_digitalWrite(LOW); + nrf24_writeRegister(RX_ADDR_P1, adr, nrf24_ADDR_LEN); + nrf24_ce_digitalWrite(HIGH); +} + +/* Returns the payload length */ +uint8_t nrf24_payload_length() { + return payload_len; +} + +/* Set the TX address */ +void nrf24_tx_address(uint8_t *adr) { + /* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */ + nrf24_writeRegister(RX_ADDR_P0, adr, nrf24_ADDR_LEN); + nrf24_writeRegister(TX_ADDR, adr, nrf24_ADDR_LEN); +} + +/* Checks if data is available for reading */ +/* Returns 1 if data is ready ... */ +uint8_t nrf24_dataReady() { + // See note in getData() function - just checking RX_DR isn't good enough + uint8_t status = nrf24_getStatus(); + + // We can short circuit on RX_DR, but if it's not set, we still need + // to check the FIFO for any pending packets + if (status & (1 << RX_DR)) { + return 1; + } + + return !nrf24_rxFifoEmpty();; +} + +/* Checks if receive FIFO is empty or not */ +uint8_t nrf24_rxFifoEmpty() { + uint8_t fifoStatus; + + nrf24_readRegister(FIFO_STATUS, &fifoStatus, 1); + + return (fifoStatus & (1 << RX_EMPTY)); +} + +/* Returns the length of data waiting in the RX fifo */ +uint8_t nrf24_payloadLength() { + uint8_t status; + nrf24_csn_digitalWrite(LOW); + spi_transfer(R_RX_PL_WID); + status = spi_transfer(0x00); + return status; +} + +/* Reads payload bytes into data array */ +void nrf24_getData(uint8_t *data) { + /* Pull down chip select */ + nrf24_csn_digitalWrite(LOW); + + /* Send cmd to read rx payload */ + spi_transfer(R_RX_PAYLOAD); + + /* Read payload */ + nrf24_transferSync(data, data, payload_len); + + /* Pull up chip select */ + nrf24_csn_digitalWrite(HIGH); + + /* Reset status register */ + nrf24_configRegister(STATUS, (1 << RX_DR)); +} + +/* Returns the number of retransmissions occured for the last message */ +uint8_t nrf24_retransmissionCount() { + uint8_t rv; + nrf24_readRegister(OBSERVE_TX, &rv, 1); + rv = rv & 0x0F; + return rv; +} + +// Sends a data package to the default address. Be sure to send the correct +// amount of bytes as configured as payload on the receiver. +void nrf24_send(uint8_t *value) { + /* Go to Standby-I first */ + nrf24_ce_digitalWrite(LOW); + + /* Set to transmitter mode , Power up if needed */ + nrf24_powerUpTx(); + + /* Do we really need to flush TX fifo each time ? */ +#if 1 + /* Pull down chip select */ + nrf24_csn_digitalWrite(LOW); + + /* Write cmd to flush transmit FIFO */ + spi_transfer(FLUSH_TX); + + /* Pull up chip select */ + nrf24_csn_digitalWrite(HIGH); +#endif + + /* Pull down chip select */ + nrf24_csn_digitalWrite(LOW); + + /* Write cmd to write payload */ + spi_transfer(W_TX_PAYLOAD); + + /* Write payload */ + nrf24_transmitSync(value, payload_len); + + /* Pull up chip select */ + nrf24_csn_digitalWrite(HIGH); + + /* Start the transmission */ + nrf24_ce_digitalWrite(HIGH); +} + +uint8_t nrf24_isSending() { + uint8_t status; + + /* read the current status */ + status = nrf24_getStatus(); + + /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */ + if ((status & ((1 << TX_DS) | (1 << MAX_RT)))) { + return 0; /* false */ + } + + return 1; /* true */ + +} + +uint8_t nrf24_getStatus() { + uint8_t rv; + nrf24_csn_digitalWrite(LOW); + rv = spi_transfer(NOP); + nrf24_csn_digitalWrite(HIGH); + return rv; +} + +uint8_t nrf24_lastMessageStatus() { + uint8_t rv; + + rv = nrf24_getStatus(); + + /* Transmission went OK */ + if ((rv & ((1 << TX_DS)))) { + return NRF24_TRANSMISSON_OK; + } + /* Maximum retransmission count is reached */ + /* Last message probably went missing ... */ + else if ((rv & ((1 << MAX_RT)))) { + return NRF24_MESSAGE_LOST; + } + /* Probably still sending ... */ + else { + return 0xFF; + } +} + +void nrf24_powerUpRx() { + nrf24_csn_digitalWrite(LOW); + spi_transfer(FLUSH_RX); + nrf24_csn_digitalWrite(HIGH); + + nrf24_configRegister(STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); + + nrf24_ce_digitalWrite(LOW); + nrf24_configRegister(CONFIG, nrf24_CONFIG | ((1 << PWR_UP) | (1 << PRIM_RX))); + nrf24_ce_digitalWrite(HIGH); +} + +void nrf24_powerUpTx() { + nrf24_configRegister(STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); + + nrf24_configRegister(CONFIG, nrf24_CONFIG | ((1 << PWR_UP) | (0 << PRIM_RX))); +} + +void nrf24_powerDown() { + nrf24_ce_digitalWrite(LOW); + nrf24_configRegister(CONFIG, nrf24_CONFIG); +} + +/* software spi routine */ +uint8_t spi_transfer(uint8_t tx) { + uint8_t i = 0; + uint8_t rx = 0; + + nrf24_sck_digitalWrite(LOW); + + for (i = 0; i < 8; i++) { + + if (tx & (1 << (7 - i))) { + nrf24_mosi_digitalWrite(HIGH); + } + else { + nrf24_mosi_digitalWrite(LOW); + } + + nrf24_sck_digitalWrite(HIGH); + + rx = rx << 1; + if (nrf24_miso_digitalRead()) { + rx |= 0x01; + } + + nrf24_sck_digitalWrite(LOW); + + } + + return rx; +} + +/* send and receive multiple bytes over SPI */ +void nrf24_transferSync(uint8_t *dataout, uint8_t *datain, uint8_t len) { + uint8_t i; + + for (i = 0; i < len; i++) { + datain[i] = spi_transfer(dataout[i]); + } + +} + +/* send multiple bytes over SPI */ +void nrf24_transmitSync(uint8_t *dataout, uint8_t len) { + uint8_t i; + + for (i = 0; i < len; i++) { + spi_transfer(dataout[i]); + } + +} + +/* Clocks only one byte into the given nrf24 register */ +void nrf24_configRegister(uint8_t reg, uint8_t value) { + nrf24_csn_digitalWrite(LOW); + spi_transfer(W_REGISTER | (REGISTER_MASK & reg)); + spi_transfer(value); + nrf24_csn_digitalWrite(HIGH); +} + +/* Read single register from nrf24 */ +void nrf24_readRegister(uint8_t reg, uint8_t *value, uint8_t len) { + nrf24_csn_digitalWrite(LOW); + spi_transfer(R_REGISTER | (REGISTER_MASK & reg)); + nrf24_transferSync(value, value, len); + nrf24_csn_digitalWrite(HIGH); +} + +/* Write to a single register of nrf24 */ +void nrf24_writeRegister(uint8_t reg, uint8_t *value, uint8_t len) { + nrf24_csn_digitalWrite(LOW); + spi_transfer(W_REGISTER | (REGISTER_MASK & reg)); + nrf24_transmitSync(value, len); + nrf24_csn_digitalWrite(HIGH); +} +``` + +Первая проверка без заднего хода: + +{{< youtube d0INQcEuwmg >}} + +Проверка с задним ходом: + +{{< youtube LrE-XA4EGXk >}} + +Геймпад: + +[Мануал по структурам пакетов геймпада](http://store.curiousinventor.com/guides/ps2) + +[Оригинальная библиотека для геймпада](http://digitalcave.ca/resources/avr/psx.jsp) + +nrf24: + +[Оригинальная библиоткека nRF24 на GitHub](https://github.com/kehribar/nrf24L01_plus) \ No newline at end of file diff --git a/content/posts/nrf-dualshock/miniature.jpg b/content/posts/nrf-dualshock/miniature.jpg new file mode 100644 index 0000000..cc2a6b9 Binary files /dev/null and b/content/posts/nrf-dualshock/miniature.jpg differ diff --git a/content/posts/nrf-dualshock/nrf24l01.jpg b/content/posts/nrf-dualshock/nrf24l01.jpg new file mode 100644 index 0000000..f49f15e Binary files /dev/null and b/content/posts/nrf-dualshock/nrf24l01.jpg differ diff --git a/content/posts/nrf-dualshock/psx_packet.png b/content/posts/nrf-dualshock/psx_packet.png new file mode 100644 index 0000000..7a11d0b Binary files /dev/null and b/content/posts/nrf-dualshock/psx_packet.png differ diff --git a/content/posts/qtcreator-stm32/aboutmodules.png b/content/posts/qtcreator-stm32/aboutmodules.png new file mode 100644 index 0000000..7a15aab Binary files /dev/null and b/content/posts/qtcreator-stm32/aboutmodules.png differ diff --git a/content/posts/qtcreator-stm32/adddev.png b/content/posts/qtcreator-stm32/adddev.png new file mode 100644 index 0000000..30ccbbd Binary files /dev/null and b/content/posts/qtcreator-stm32/adddev.png differ diff --git a/content/posts/qtcreator-stm32/armgccadd.png b/content/posts/qtcreator-stm32/armgccadd.png new file mode 100644 index 0000000..a604016 Binary files /dev/null and b/content/posts/qtcreator-stm32/armgccadd.png differ diff --git a/content/posts/qtcreator-stm32/armgccfiles.png b/content/posts/qtcreator-stm32/armgccfiles.png new file mode 100644 index 0000000..8a02904 Binary files /dev/null and b/content/posts/qtcreator-stm32/armgccfiles.png differ diff --git a/content/posts/qtcreator-stm32/armgdb.png b/content/posts/qtcreator-stm32/armgdb.png new file mode 100644 index 0000000..0b1bfcb Binary files /dev/null and b/content/posts/qtcreator-stm32/armgdb.png differ diff --git a/content/posts/qtcreator-stm32/armtoolchain.png b/content/posts/qtcreator-stm32/armtoolchain.png new file mode 100644 index 0000000..e5d79d5 Binary files /dev/null and b/content/posts/qtcreator-stm32/armtoolchain.png differ diff --git a/content/posts/qtcreator-stm32/baremetal.png b/content/posts/qtcreator-stm32/baremetal.png new file mode 100644 index 0000000..e5e6949 Binary files /dev/null and b/content/posts/qtcreator-stm32/baremetal.png differ diff --git a/content/posts/qtcreator-stm32/buildsuccess.png b/content/posts/qtcreator-stm32/buildsuccess.png new file mode 100644 index 0000000..8b0fcd0 Binary files /dev/null and b/content/posts/qtcreator-stm32/buildsuccess.png differ diff --git a/content/posts/qtcreator-stm32/debugcfg.png b/content/posts/qtcreator-stm32/debugcfg.png new file mode 100644 index 0000000..d9eca16 Binary files /dev/null and b/content/posts/qtcreator-stm32/debugcfg.png differ diff --git a/content/posts/qtcreator-stm32/execcfg.png b/content/posts/qtcreator-stm32/execcfg.png new file mode 100644 index 0000000..be6b1fe Binary files /dev/null and b/content/posts/qtcreator-stm32/execcfg.png differ diff --git a/content/posts/qtcreator-stm32/gdbasync.png b/content/posts/qtcreator-stm32/gdbasync.png new file mode 100644 index 0000000..64c4978 Binary files /dev/null and b/content/posts/qtcreator-stm32/gdbasync.png differ diff --git a/content/posts/qtcreator-stm32/impormake.png b/content/posts/qtcreator-stm32/impormake.png new file mode 100644 index 0000000..bcf7ccf Binary files /dev/null and b/content/posts/qtcreator-stm32/impormake.png differ diff --git a/content/posts/qtcreator-stm32/index.md b/content/posts/qtcreator-stm32/index.md new file mode 100644 index 0000000..81157ec --- /dev/null +++ b/content/posts/qtcreator-stm32/index.md @@ -0,0 +1,128 @@ +--- +title: "Программируем и отлаживаем STM32 в QtCreator" +categories: ["mcu", "archive"] +date: 2017-02-27T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Однажды понадобилось написать программку с использованием Qt. Как выяснилось, лучше всего это делать в специализированной для этого дела среде разработки - QtCreator. Поработав в ней некоторое время я понял, что это весьма неплохая IDE. И решил попробовать использовать её не совсем по назначению - программировать STM32. + + + + +Итак, что нам понадобится (далее рассматривается windows, но для остальных ОС мало что изменится): + +1. QtCreator, вестимо +2. [Python 2.7](https://www.python.org/downloads/) (нужен для отладчика) +3. [MinGW](https://sourceforge.net/projects/mingw/files/) +4. [ARM Embedded Toolchain](https://launchpad.net/gcc-arm-embedded/+download) +5. [OpenOCD](http://openocd.org/getting-openocd/) +6. [Проект с makefile для stm32](../stm32f1x-makefile) (можно и другие системы сборки, которые поддерживает QtCreator). + +Установку QtCreator рассматривать не буду, про MinGW знает, наверное, каждый, кто пишет на Qt по Windows. Из этого пакета нам понадобится только утилита make. Папку с исполняемыми файлами MinGW я добавил в системную переменную PATH. Python также устанавливаем в PATH. + +![|310](pypath.png) + +Далее устанавливаем ARM тулчейн. Ну как устанавливаем - скачиваем zip версию и распаковываем в удобное место. + +После распаковки: + +![|](armgccfiles.png) + +Папку bin также добавляем в PATH. + +С OpenOCD те же манипуляции - распаковываем, добавляем bin (или bin-x64 для 64-разрядных систем) в PATH. + +![|](openocdfiles.png) + +Открываем консоль и проверяем наличие всех программ (просто ввводим make, arm-none-eabi-gcc, openocd). Картина должна быть такой: + +![|](vseok.png) + +Теперь начинаются пляски с QtCreator. Первым делом нужно включить плагин для "голого железа" - **BareMetal**. Для этого заходим в **Справка** -> **О Модулях...** + +![|](aboutmodules.png) + +И включаем там **BareMetal**. Перезапускаем QtCreator. + +![|](baremetal.png) + +Далее добавляем наш компилятор. Заходим в **Инструменты** -> **Параметры**. + +Находим там категорию **Сборка и запуск**. Открываем вкладку **Компилятор**, нажимаем **Добавить** -> **GCC** -> **C**. Прописываем полный путь к **arm-none-eabi-gcc.exe** или просто пишем **arm-none-eabi-gcc**. Обзываем как угодно, я назвал ARM-GCC. + +![|545](armgccadd.png) + +При надобности те же манипуляции проводим с **arm-none-eabi-g++**, выбрав** C++**. + +Тыкаем применить. + +Теперь неплохо бы добавить устройство. Сначала выбираем сервер отладки. Открываем категорию **Устройства**, потом вкладку **Голое железо**. Жмём **Добавить** - **OpenOCD**. Ничего не меняем, жмём применить. Да, QtCreator может запускать openocd автоматически, но моя сборка не может. Как я организовал автоматический запуск будет написано в конце. Тыкаем **Применить**. + +![|517](ocdcfg.png) + +Добавляем само устройство. Открываем вкладку **Устройства**, жмём **Добавить** -> **Голое железо**. Обзываем как-то (я обозвал stm32). Выбираем **OpenOCD**. + +![|353](adddev.png) + +Ну и **Завершить**, **Применить**, естетственно. + +Теперь добавляем отладчик. Снова открываем категорию **Сборка и запуск**, выбираем вкладку **Отладчики** , добавляем новый и прописываем туда **arm-none-eabi-gdb-py** (именно с суффиксом **py**, так как QtCreator'у нужна версия отладчика с поддержкой питона). Обзываем arm-gdb или как-то ещё. **Применить**. + +![|354](armgdb.png) + +Добавляем тулчейн. Выбираем вкладку **Комплекты** и добавляем новый. Обзываем и выбираем компиляторы, отладчик, устройство. + +![|638](armtoolchain.png) + +И последнее - категория **Отладчик**, вкладка **GDB, расширенные** и включаем там **Использовать асинхронный режим**... Без этого QtCreator при отладке будет падать. + +![|](gdbasync.png) + +Жмём **OK**. Всё. + +Добавляем наш [проект](../stm32f1x-makefile): + +![|](impormake.png) + +![|](prjfiles.png) + +![|667](prjwnd.png) + +Открываем вкладку проекты, слева отключаем Qt, выбираем наш тулчейн, добавляем/настраиваем команды сборки: + +![|625](debugcfg.png) + +Пробуем собрать: + +![|621](buildsuccess.png) + +Снова открываем проекты, настраиваем запуск. Конфигурация запуска -** через сервер GDB**. В качестве программы нужно выбрать скомпилированный **elf** файл: + +![|470](execcfg.png) + +Теперь пора проверять что получилось. Запускаем OpenOCD вручную через cmd (для моей stm32f103c8t6): + +```cmd +openocd -f /interface/stlink-v2.cfg -f target/stm32f1x.cfg +``` + +![|](ocdlog.png) + +В QtCreator куда-то ставим брэйкпоинт и наконец-то запускаем отладку: + +![|](wtf.png) + +Почему Command aborted? Да потому что я не применил изменения и у меня запускался обычный GDB от MinGW. + +Исправляю, запускаю: + +![647](yay.png) + +Бинго! + +Да, про автоматический запуск. Прошу простить, инструкции не будет, так как это был костыль с правкой плагина HEX редактором. Если в новых версиях QtCreator это не исправят, то напишу тут. + +[Makefile для STM32F103](../stm32f1x-makefile) diff --git a/content/posts/qtcreator-stm32/m_2017-02-27_154445.png b/content/posts/qtcreator-stm32/m_2017-02-27_154445.png new file mode 100644 index 0000000..b83b619 Binary files /dev/null and b/content/posts/qtcreator-stm32/m_2017-02-27_154445.png differ diff --git a/content/posts/qtcreator-stm32/miniature.jpg b/content/posts/qtcreator-stm32/miniature.jpg new file mode 100644 index 0000000..5330c06 Binary files /dev/null and b/content/posts/qtcreator-stm32/miniature.jpg differ diff --git a/content/posts/qtcreator-stm32/ocdcfg.png b/content/posts/qtcreator-stm32/ocdcfg.png new file mode 100644 index 0000000..3a27f2b Binary files /dev/null and b/content/posts/qtcreator-stm32/ocdcfg.png differ diff --git a/content/posts/qtcreator-stm32/ocdlog.png b/content/posts/qtcreator-stm32/ocdlog.png new file mode 100644 index 0000000..8f830d6 Binary files /dev/null and b/content/posts/qtcreator-stm32/ocdlog.png differ diff --git a/content/posts/qtcreator-stm32/openocdfiles.png b/content/posts/qtcreator-stm32/openocdfiles.png new file mode 100644 index 0000000..3aa20ab Binary files /dev/null and b/content/posts/qtcreator-stm32/openocdfiles.png differ diff --git a/content/posts/qtcreator-stm32/prjfiles.png b/content/posts/qtcreator-stm32/prjfiles.png new file mode 100644 index 0000000..645da58 Binary files /dev/null and b/content/posts/qtcreator-stm32/prjfiles.png differ diff --git a/content/posts/qtcreator-stm32/prjwnd.png b/content/posts/qtcreator-stm32/prjwnd.png new file mode 100644 index 0000000..f66a4aa Binary files /dev/null and b/content/posts/qtcreator-stm32/prjwnd.png differ diff --git a/content/posts/qtcreator-stm32/pypath.png b/content/posts/qtcreator-stm32/pypath.png new file mode 100644 index 0000000..5967d0d Binary files /dev/null and b/content/posts/qtcreator-stm32/pypath.png differ diff --git a/content/posts/qtcreator-stm32/vseok.png b/content/posts/qtcreator-stm32/vseok.png new file mode 100644 index 0000000..b83b619 Binary files /dev/null and b/content/posts/qtcreator-stm32/vseok.png differ diff --git a/content/posts/qtcreator-stm32/wtf.png b/content/posts/qtcreator-stm32/wtf.png new file mode 100644 index 0000000..45508cc Binary files /dev/null and b/content/posts/qtcreator-stm32/wtf.png differ diff --git a/content/posts/qtcreator-stm32/yay.png b/content/posts/qtcreator-stm32/yay.png new file mode 100644 index 0000000..2994ccf Binary files /dev/null and b/content/posts/qtcreator-stm32/yay.png differ diff --git a/content/posts/rdu3232/assembly.jpg b/content/posts/rdu3232/assembly.jpg new file mode 100644 index 0000000..c781101 Binary files /dev/null and b/content/posts/rdu3232/assembly.jpg differ diff --git a/content/posts/rdu3232/compass.jpg b/content/posts/rdu3232/compass.jpg new file mode 100644 index 0000000..6766969 Binary files /dev/null and b/content/posts/rdu3232/compass.jpg differ diff --git a/content/posts/rdu3232/disism.jpg b/content/posts/rdu3232/disism.jpg new file mode 100644 index 0000000..a4af25c Binary files /dev/null and b/content/posts/rdu3232/disism.jpg differ diff --git a/content/posts/rdu3232/index.md b/content/posts/rdu3232/index.md new file mode 100644 index 0000000..f707adb --- /dev/null +++ b/content/posts/rdu3232/index.md @@ -0,0 +1,44 @@ +--- +title: "Робот с дистанционным управлением" +categories: ["mcu", "archive"] +date: 2017-02-23T00:00:00+03:00 +draft: true +--- + +Черновик + + + +Робот с управлением по беспроводному каналу связи. В качестве радиомодулей используются недорогие радиомодули nrf24l01. Управляющим контроллером робота является ATmega8, программа написана на языке c. + +Для перемещения робота используются два независимых друг от друга шасси. + +![Конструкция робота|406](disism.jpg) + +Робот оснащён следующими датчиками: + +* Расстояния. С помощью датчика расстояния (дальномера) робот может находить препятствия и отправлять расстояние них пользователю. Однако основное назначение датчика - находить объекты, которые можно подобрать захватом. В качестве датчика расстояния служит ультразвуковой дальномер HC-SR04. + +![Дальномер в тыльной части робота|273](range.jpg) + + +* Препятствия. Датчик находится непосредственно под захватом. Датчик служит для подтверждения удачного захвата объекта роботом. +* Поворота (электронный компас). Наличие этого датчика добавляет роботу понятие текущего угла поворота, что важно для сканирования на предмет препятствий или объектов для захвата. Модель датчика - HMC5883L. + +![Датчик поворота, установленный на мачте|276](compass.jpg) + + +Робот также оснащён манипулятором для выполнения "полезной" работы. Управление роботом происходит с компьютера через особый модуль (\[usb\]->ft232->\[uart\]->atmega8->\[SPI\]->nrf24l01). Программа для визуального наблюдения за роботом написана на языке c, подключена библиотека fltk, использовались платформонезависимые функции, благодаря чему программа собирается и запускается не только на Windows. + +![|343](tc.png) + +Немного фото: + +![Робот без манипулятора|556](pirate.jpg) + +![Непосредственно захват|273](manip.jpg) + +![Робот с захватом, компас снят|273](assembly.jpg) + + +{{< youtube _36egDgc_6s >}} diff --git a/content/posts/rdu3232/manip.jpg b/content/posts/rdu3232/manip.jpg new file mode 100644 index 0000000..b85855a Binary files /dev/null and b/content/posts/rdu3232/manip.jpg differ diff --git a/content/posts/rdu3232/pirate.jpg b/content/posts/rdu3232/pirate.jpg new file mode 100644 index 0000000..1e1044c Binary files /dev/null and b/content/posts/rdu3232/pirate.jpg differ diff --git a/content/posts/rdu3232/range.jpg b/content/posts/rdu3232/range.jpg new file mode 100644 index 0000000..5ab2e46 Binary files /dev/null and b/content/posts/rdu3232/range.jpg differ diff --git a/content/posts/rdu3232/tc.png b/content/posts/rdu3232/tc.png new file mode 100644 index 0000000..bbc71f2 Binary files /dev/null and b/content/posts/rdu3232/tc.png differ diff --git a/content/posts/utf8-mingw/index.md b/content/posts/utf8-mingw/index.md new file mode 100644 index 0000000..1213c2c --- /dev/null +++ b/content/posts/utf8-mingw/index.md @@ -0,0 +1,47 @@ +--- +title: "UTF-8 и MinGW" +categories: ["cpp", "archive"] +date: 2015-12-03T00:00:00+03:00 +draft: false +featured_image: miniature.jpg +--- + + +Наверное, любой сталкивался с проблемой русских букв в консоли. И каждый придумывал свои костыли. Вот и я свой придумал. + + + +Имеем мы все файлы в кодировке **UTF-8**. А для нормального вывода в консоль Windows нужны исходники в кодировке 1252. Конвертировать? + +Зачем? Ведь компилятор это умеет. + +Так что кормим компилятору вот такие параметры: + +```cmd +-finput-charset=utf-8 -fexec-charset=cp1252 +``` + +А вывод должен иметь следующий вид: + +```c +wprintf(L"Да это же русские буквы =О"); +``` + +Нужно не забывать добавлять **L** до строки, а также вызвать **setlocale**. + +Пример: + +```c +#include +#include + +int main() { + setlocale(LC_ALL, ""); + wprintf(L"Да это же русские буквы =О\n\n"); + wprintf(L"Нажмите [Enter] для продолжения..."); + getchar(); + return 0; +} +``` + +![result](m_2015-12-03_181957.png "Результат") \ No newline at end of file diff --git a/content/posts/utf8-mingw/m_2015-12-03_181957.png b/content/posts/utf8-mingw/m_2015-12-03_181957.png new file mode 100644 index 0000000..11e720a Binary files /dev/null and b/content/posts/utf8-mingw/m_2015-12-03_181957.png differ diff --git a/content/posts/utf8-mingw/miniature.jpg b/content/posts/utf8-mingw/miniature.jpg new file mode 100644 index 0000000..ebfa698 Binary files /dev/null and b/content/posts/utf8-mingw/miniature.jpg differ diff --git a/public/.gitignore b/public/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/themes/mmotium/LICENSE b/themes/mmotium/LICENSE new file mode 100644 index 0000000..147d594 --- /dev/null +++ b/themes/mmotium/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2022 YOUR_NAME_HERE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/themes/mmotium/archetypes/default.md b/themes/mmotium/archetypes/default.md new file mode 100644 index 0000000..ac36e06 --- /dev/null +++ b/themes/mmotium/archetypes/default.md @@ -0,0 +1,2 @@ ++++ ++++ diff --git a/themes/mmotium/assets/css/_base.scss b/themes/mmotium/assets/css/_base.scss new file mode 100644 index 0000000..60fa0e2 --- /dev/null +++ b/themes/mmotium/assets/css/_base.scss @@ -0,0 +1,39 @@ +*, +*:before, +*:after { + box-sizing: border-box; +} + +body { + font-size: 16px; + font-family: $main_font, Helvetica, sans-serif; + line-height: normal; + color: $font-color; + background: url($page-bg-image) repeat scroll 0 0 $page-bg-color; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; +} + +a:link, +a:visited { + text-decoration: none; + color: $link-color; +} + + +a:hover, +a:active { + color: $link-hover-color; +} + +pre { + max-height: 512px; + overflow: auto; +} \ No newline at end of file diff --git a/themes/mmotium/assets/css/_font.scss b/themes/mmotium/assets/css/_font.scss new file mode 100644 index 0000000..1f8f45c --- /dev/null +++ b/themes/mmotium/assets/css/_font.scss @@ -0,0 +1,21 @@ +$main_font: 'Open Sans'; + +/* open-sans-regular - latin_cyrillic */ +@font-face { + font-family: $main_font; + font-style: normal; + font-weight: 400; + src: url('/vendor/fonts/open-sans-v34-latin_cyrillic-regular.eot'); + /* IE9 Compat Modes */ + src: local(''), + url('/vendor/fonts/open-sans-v34-latin_cyrillic-regular.eot?#iefix') format('embedded-opentype'), + /* IE6-IE8 */ + url('/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff2') format('woff2'), + /* Super Modern Browsers */ + url('/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff') format('woff'), + /* Modern Browsers */ + url('/vendor/fonts/open-sans-v34-latin_cyrillic-regular.ttf') format('truetype'), + /* Safari, Android, iOS */ + url('/vendor/fonts/open-sans-v34-latin_cyrillic-regular.svg#OpenSans') format('svg'); + /* Legacy iOS */ +} \ No newline at end of file diff --git a/themes/mmotium/assets/css/_vars.scss b/themes/mmotium/assets/css/_vars.scss new file mode 100644 index 0000000..9b3d89d --- /dev/null +++ b/themes/mmotium/assets/css/_vars.scss @@ -0,0 +1,19 @@ +$container-width: 1200px; +$tablet-width: 768px; + +$font-color: #333333; + +$navbar-color: #2262b1; +$navbar-text-color: white; +$link-color: #00465c; +$link-hover-color: #0096c4; +$tag-color: #728fb6; + +$page-bg-color: #784323; +$page-bg-image: "/images/bg.jpg"; +$post-bg-color: white; + +$image-wrappper-bg-color: #fcfcfc; +$image-wrappper-border-color: #d6d6d6; + +$table-border-color: #d6d6d6; \ No newline at end of file diff --git a/themes/mmotium/assets/css/normalize.css b/themes/mmotium/assets/css/normalize.css new file mode 100644 index 0000000..192eb9c --- /dev/null +++ b/themes/mmotium/assets/css/normalize.css @@ -0,0 +1,349 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/themes/mmotium/assets/css/style.scss b/themes/mmotium/assets/css/style.scss new file mode 100644 index 0000000..c9f166a --- /dev/null +++ b/themes/mmotium/assets/css/style.scss @@ -0,0 +1,166 @@ +@import 'normalize'; +@import '_vars'; +@import '_font'; +@import '_base'; + +.container { + width: 100%; + max-width: $container-width; + margin: 0 auto; +} + +nav.navbar { + & { + background-color: $navbar-color; + color: $navbar-text-color; + font-size: 1.5rem; + padding: 10px 0; + margin-bottom: 1rem; + } + + .container { + padding: 0 24px; + } + + a:link, + a:visited { + color: $navbar-text-color; + text-decoration: none; + } +} + +.post.single { + & { + background-color: $post-bg-color; + padding: 24px; + } + + .image-wrapper { + & { + display: inline-block; + text-align: center; + margin: 0; + padding: 16px; + background-color: $image-wrappper-bg-color; + border: 1px solid $image-wrappper-border-color; + } + + img { + width: 100%; + } + + figcaption { + margin-top: 16px; + } + } + + table { + border-collapse: collapse; + } + + table, + th, + td { + border: 1px solid $table-border-color; + } + + th, + td { + padding: 0.3rem; + } +} + + +section.posts { + & { + display: flex; + flex-direction: column; + gap: 16px; + } + + .post { + background-color: $post-bg-color; + padding: 24px; + } + + .thumb { + float: left; + margin-right: 16px; + margin-bottom: 16px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + // border: 1px solid #ccc; + } + + + header { + margin-bottom: 1rem; + } + + .body::after { + content: " "; + clear: both; + display: block; + } + + footer { + margin-top: 1rem; + } + + footer time { + color: #aaa; + margin-right: 0.5rem; + } + + footer .category { + color: $tag-color; + border: 1px solid $tag-color; + padding: 0 0.5rem; + } +} + +.page-wrapper { + & { + display: flex; + flex-direction: row; + gap: 16px; + } + + @media (max-width: $tablet-width) { + & { + flex-direction: column; + } + } + + .sidebar { + & { + display: flex; + flex-direction: column; + min-width: 300px; + gap: 16px; + } + + .item { + background-color: $post-bg-color; + padding: 24px; + } + + h4 { + margin-bottom: 16px; + } + + ul { + list-style-type: "- "; + list-style-position: inside; + padding: 0; + margin: 0; + } + + p { + margin: 0; + } + } +} + +.page-footer { + min-height: 16px; +} \ No newline at end of file diff --git a/themes/mmotium/layouts/404.html b/themes/mmotium/layouts/404.html new file mode 100644 index 0000000..3252bff --- /dev/null +++ b/themes/mmotium/layouts/404.html @@ -0,0 +1,13 @@ +{{ define "main" }} +
+ +
+

404

+
+ +

+ Такой страницы нет. Может была когда-то но сайчас её нет. +

+ +
+{{ end }} \ No newline at end of file diff --git a/themes/mmotium/layouts/_default/_markup/render-image.html b/themes/mmotium/layouts/_default/_markup/render-image.html new file mode 100644 index 0000000..de6fa55 --- /dev/null +++ b/themes/mmotium/layouts/_default/_markup/render-image.html @@ -0,0 +1,25 @@ +
+ {{/* Remote image */ -}} + {{ if or (hasPrefix .Destination "https://") (hasPrefix .Destination "http://") }} + + {{.Text}} + + {{/* Local image */ -}} + {{ else }} + {{- $img := .Page.Resources.GetMatch .Destination -}} + {{- $resizeMimes := slice "image/png" "image/jpeg" -}} + {{ if $img -}} + + {{ if in $resizeMimes $img.MediaType.Type -}} + {{.Text}} + {{- else -}} + {{.Text}} + {{- end -}} + + {{- else -}} + {{.Text}} + {{- end -}} + {{- end -}} + + {{ if .Title }}
{{ .Title }}
{{ end }} +
diff --git a/themes/mmotium/layouts/_default/baseof.html b/themes/mmotium/layouts/_default/baseof.html new file mode 100644 index 0000000..5f46d80 --- /dev/null +++ b/themes/mmotium/layouts/_default/baseof.html @@ -0,0 +1,28 @@ + + + + + + + + + {{ block "head_meta" . }}{{ end }} + + {{ $sassOptions := (dict "outputStyle" "compressed") -}} + {{- $style := resources.Get "css/style.scss" | resources.ToCSS $sassOptions | fingerprint -}} + + + + + {{ block "title" . }}{{ with .Params.Title }}{{ . }} | {{ end }}{{ .Site.Title }}{{ end }} + + + {{ partial "header.html" . }} + +
+ {{ block "main" . }}{{ end }} +
+ + {{ partial "footer.html" . }} + + diff --git a/themes/mmotium/layouts/_default/list.html b/themes/mmotium/layouts/_default/list.html new file mode 100644 index 0000000..4867d77 --- /dev/null +++ b/themes/mmotium/layouts/_default/list.html @@ -0,0 +1,3 @@ +{{ define "main" }} +чё за лист +{{ end }} \ No newline at end of file diff --git a/themes/mmotium/layouts/_default/single.html b/themes/mmotium/layouts/_default/single.html new file mode 100644 index 0000000..d385014 --- /dev/null +++ b/themes/mmotium/layouts/_default/single.html @@ -0,0 +1,20 @@ +{{ define "head_meta" }} + + + + + {{ with .PublishDate }}{{ end }} + {{ with .Lastmod }}{{ end }} + {{ $thumb := $.Resources.Get $.Params.featured_image -}} + {{ with $thumb }}{{end}} +{{end}} + +{{ define "main" }} +
+

{{ .Title }}

+ +

+ {{- .Content -}} +

+
+{{ end }} \ No newline at end of file diff --git a/themes/mmotium/layouts/categories/taxonomy.html b/themes/mmotium/layouts/categories/taxonomy.html new file mode 100644 index 0000000..da0ec8b --- /dev/null +++ b/themes/mmotium/layouts/categories/taxonomy.html @@ -0,0 +1,20 @@ +{{ define "main" }} + + +
+
+

Категория - {{ .Title }}

+

{{ .Params.description }}

+
+ +

Тут есть:

+ + +
+ + +{{ end }} \ No newline at end of file diff --git a/themes/mmotium/layouts/index.html b/themes/mmotium/layouts/index.html new file mode 100644 index 0000000..86c2251 --- /dev/null +++ b/themes/mmotium/layouts/index.html @@ -0,0 +1,36 @@ +{{ define "main" }} + +
+
+ {{ range where .Site.RegularPages "Section" "posts" }} +
+
+

+ {{.Title}} +

+
+
+ {{- $thumb := .Page.Resources.Get .Params.featured_image -}} + {{if $thumb}} + + + + {{end}} + +
+ {{.Summary}} +
+
+
+ + {{ range (.GetTerms "categories") }} + {{ .LinkTitle }} + {{ end }} +
+
+ {{ end }} +
+ + {{ partial "sidebar.html" . }} +
+{{ end }} diff --git a/themes/mmotium/layouts/partials/footer.html b/themes/mmotium/layouts/partials/footer.html new file mode 100644 index 0000000..b233c88 --- /dev/null +++ b/themes/mmotium/layouts/partials/footer.html @@ -0,0 +1,5 @@ +
+
+ +
+
\ No newline at end of file diff --git a/themes/mmotium/layouts/partials/header.html b/themes/mmotium/layouts/partials/header.html new file mode 100644 index 0000000..4c9afaf --- /dev/null +++ b/themes/mmotium/layouts/partials/header.html @@ -0,0 +1,7 @@ +
+ +
\ No newline at end of file diff --git a/themes/mmotium/layouts/partials/sidebar.html b/themes/mmotium/layouts/partials/sidebar.html new file mode 100644 index 0000000..5b65cf3 --- /dev/null +++ b/themes/mmotium/layouts/partials/sidebar.html @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/themes/mmotium/static/images/bg.jpg b/themes/mmotium/static/images/bg.jpg new file mode 100644 index 0000000..ffc395a Binary files /dev/null and b/themes/mmotium/static/images/bg.jpg differ diff --git a/themes/mmotium/static/images/favicon.png b/themes/mmotium/static/images/favicon.png new file mode 100644 index 0000000..635ffa1 Binary files /dev/null and b/themes/mmotium/static/images/favicon.png differ diff --git a/themes/mmotium/static/images/image-error.png b/themes/mmotium/static/images/image-error.png new file mode 100644 index 0000000..3bafe7e Binary files /dev/null and b/themes/mmotium/static/images/image-error.png differ diff --git a/themes/mmotium/static/images/retard.jpg b/themes/mmotium/static/images/retard.jpg new file mode 100644 index 0000000..901e397 Binary files /dev/null and b/themes/mmotium/static/images/retard.jpg differ diff --git a/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.eot b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.eot new file mode 100644 index 0000000..d5c7c41 Binary files /dev/null and b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.eot differ diff --git a/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.svg b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.svg new file mode 100644 index 0000000..f6bfcca --- /dev/null +++ b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.svg @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.ttf b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.ttf new file mode 100644 index 0000000..5c597e2 Binary files /dev/null and b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.ttf differ diff --git a/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff new file mode 100644 index 0000000..7b1051a Binary files /dev/null and b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff differ diff --git a/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff2 b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff2 new file mode 100644 index 0000000..91f473d Binary files /dev/null and b/themes/mmotium/static/vendor/fonts/open-sans-v34-latin_cyrillic-regular.woff2 differ diff --git a/themes/mmotium/static/vendor/spotlight.bundle.js b/themes/mmotium/static/vendor/spotlight.bundle.js new file mode 100644 index 0000000..810ed72 --- /dev/null +++ b/themes/mmotium/static/vendor/spotlight.bundle.js @@ -0,0 +1,28 @@ +/** + * Spotlight.js v0.7.8 (Bundle) + * Copyright 2019-2021 Nextapps GmbH + * Author: Thomas Wilkerling + * Licence: Apache-2.0 + * https://github.com/nextapps-de/spotlight + */ +(function(){'use strict';var aa=document.createElement("style");aa.innerHTML="@keyframes pulsate{0%,to{opacity:1}50%{opacity:.2}}#spotlight{position:fixed;top:-1px;bottom:-1px;width:100%;z-index:99999;color:#fff;background-color:#000;opacity:0;overflow:hidden;-webkit-user-select:none;-ms-user-select:none;user-select:none;transition:opacity .2s ease-out;font-family:Arial,sans-serif;font-size:16px;font-weight:400;contain:strict;touch-action:none;pointer-events:none}#spotlight.show{opacity:1;transition:none;pointer-events:auto}#spotlight.white{color:#212529;background-color:#fff}#spotlight.white .spl-next,#spotlight.white .spl-page~*,#spotlight.white .spl-prev,#spotlight.white .spl-spinner{filter:invert(1)}#spotlight.white .spl-progress{background-color:rgba(0,0,0,.35)}#spotlight.white .spl-footer,#spotlight.white .spl-header{background-color:rgba(255,255,255,.65)}#spotlight.white .spl-button{background:#212529;color:#fff}.spl-footer,.spl-header{background-color:rgba(0,0,0,.45)}#spotlight .contain,#spotlight .cover{object-fit:cover;height:100%;width:100%}#spotlight .contain{object-fit:contain}#spotlight .autofit{object-fit:none;width:auto;height:auto;max-height:none;max-width:none;transition:none}.spl-scene,.spl-spinner,.spl-track{width:100%;height:100%;position:absolute}.spl-track{contain:strict}.spl-spinner{background-position:center;background-repeat:no-repeat;background-size:42px;opacity:0}.spl-spinner.spin{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzgiIGhlaWdodD0iMzgiIHZpZXdCb3g9IjAgMCAzOCAzOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHJva2U9IiNmZmYiPjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMSAxKSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2Utb3BhY2l0eT0iLjY1Ij48Y2lyY2xlIHN0cm9rZS1vcGFjaXR5PSIuMTUiIGN4PSIxOCIgY3k9IjE4IiByPSIxOCIvPjxwYXRoIGQ9Ik0zNiAxOGMwLTkuOTQtOC4wNi0xOC0xOC0xOCI+PGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJyb3RhdGUiIGZyb209IjAgMTggMTgiIHRvPSIzNjAgMTggMTgiIGR1cj0iMXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIi8+PC9wYXRoPjwvZz48L2c+PC9zdmc+);transition:opacity .2s linear .25s;opacity:1}.spl-spinner.error{background-image:url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjMyIiB3aWR0aD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMTYsMUExNSwxNSwwLDEsMCwzMSwxNiwxNSwxNSwwLDAsMCwxNiwxWm0wLDJhMTMsMTMsMCwwLDEsOC40NSwzLjE0TDYuMTQsMjQuNDVBMTMsMTMsMCwwLDEsMTYsM1ptMCwyNmExMywxMywwLDAsMS04LjQ1LTMuMTRMMjUuODYsNy41NUExMywxMywwLDAsMSwxNiwyOVoiIGlkPSJiYW5fc2lnbl9jcm9zc2VkX2NpcmNsZSIvPjwvc3ZnPg==);background-size:128px;transition:none;opacity:.5}.spl-scene{transition:transform .65s cubic-bezier(.1,1,.1,1);contain:layout size;will-change:transform}.spl-pane>*{position:absolute;width:auto;height:auto;max-width:100%;max-height:100%;left:50%;top:50%;margin:0;padding:0;border:0;transform:translate(-50%,-50%) scale(1);transition:transform .65s cubic-bezier(.3,1,.3,1),opacity .65s ease;contain:layout style;will-change:transform,opacity;visibility:hidden}.spl-header,.spl-pane,.spl-progress{position:absolute;top:0}.spl-pane{width:100%;height:100%;transition:transform .65s cubic-bezier(.3,1,.3,1);contain:layout size;will-change:transform,contents}.spl-header{width:100%;height:50px;text-align:right;transform:translateY(-100px);transition:transform .35s ease;overflow:hidden;will-change:transform}#spotlight.menu .spl-footer,#spotlight.menu .spl-header,.spl-footer:hover,.spl-header:hover{transform:translateY(0)}.spl-header div{display:inline-block;vertical-align:middle;white-space:nowrap;width:50px;height:50px;opacity:.5}.spl-progress{width:100%;height:3px;background-color:rgba(255,255,255,.45);transform:translateX(-100%);transition:transform linear}.spl-footer,.spl-next,.spl-prev{position:absolute;transition:transform .35s ease;will-change:transform}.spl-footer{left:0;right:0;bottom:0;line-height:20px;padding:20px 20px 0;padding-bottom:env(safe-area-inset-bottom,0);text-align:left;font-size:15px;font-weight:400;transform:translateY(100%)}.spl-title{font-size:22px}.spl-button,.spl-description,.spl-title{margin-bottom:20px}.spl-button{display:inline-block;background:#fff;color:#000;border-radius:5px;padding:10px 20px;cursor:pointer}.spl-next,.spl-page~*,.spl-prev{background-position:center;background-repeat:no-repeat}.spl-page{float:left;width:auto;line-height:50px}.spl-page~*{background-size:21px;float:right}.spl-fullscreen{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyLjUiIHZpZXdCb3g9Ii0xIC0xIDI2IDI2IiB3aWR0aD0iMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTggM0g1YTIgMiAwIDAgMC0yIDJ2M20xOCAwVjVhMiAyIDAgMCAwLTItMmgtM20wIDE4aDNhMiAyIDAgMCAwIDItMnYtM00zIDE2djNhMiAyIDAgMCAwIDIgMmgzIi8+PC9zdmc+)}.spl-fullscreen.on{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyLjUiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik04IDN2M2EyIDIgMCAwIDEtMiAySDNtMTggMGgtM2EyIDIgMCAwIDEtMi0yVjNtMCAxOHYtM2EyIDIgMCAwIDEgMi0yaDNNMyAxNmgzYTIgMiAwIDAgMSAyIDJ2MyIvPjwvc3ZnPg==)}.spl-autofit{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBoZWlnaHQ9Ijk2cHgiIHZpZXdCb3g9IjAgMCA5NiA5NiIgd2lkdGg9Ijk2cHgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoOTAgNTAgNTApIiBmaWxsPSIjZmZmIiBkPSJNNzEuMzExLDgwQzY5LjY3LDg0LjY2LDY1LjIzLDg4LDYwLDg4SDIwYy02LjYzLDAtMTItNS4zNy0xMi0xMlYzNmMwLTUuMjMsMy4zNC05LjY3LDgtMTEuMzExVjc2YzAsMi4yMSwxLjc5LDQsNCw0SDcxLjMxMSAgeiIvPjxwYXRoIHRyYW5zZm9ybT0icm90YXRlKDkwIDUwIDUwKSIgZmlsbD0iI2ZmZiIgZD0iTTc2LDhIMzZjLTYuNjMsMC0xMiw1LjM3LTEyLDEydjQwYzAsNi42Myw1LjM3LDEyLDEyLDEyaDQwYzYuNjMsMCwxMi01LjM3LDEyLTEyVjIwQzg4LDEzLjM3LDgyLjYzLDgsNzYsOHogTTgwLDYwICBjMCwyLjIxLTEuNzksNC00LDRIMzZjLTIuMjEsMC00LTEuNzktNC00VjIwYzAtMi4yMSwxLjc5LTQsNC00aDQwYzIuMjEsMCw0LDEuNzksNCw0VjYweiIvPjwvc3ZnPg==)}.spl-zoom-in,.spl-zoom-out{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIxMSIgY3k9IjExIiByPSI4Ii8+PGxpbmUgeDE9IjIxIiB4Mj0iMTYuNjUiIHkxPSIyMSIgeTI9IjE2LjY1Ii8+PGxpbmUgeDE9IjgiIHgyPSIxNCIgeTE9IjExIiB5Mj0iMTEiLz48L3N2Zz4=);background-size:22px}.spl-zoom-in{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIxMSIgY3k9IjExIiByPSI4Ii8+PGxpbmUgeDE9IjIxIiB4Mj0iMTYuNjUiIHkxPSIyMSIgeTI9IjE2LjY1Ii8+PGxpbmUgeDE9IjExIiB4Mj0iMTEiIHkxPSI4IiB5Mj0iMTQiLz48bGluZSB4MT0iOCIgeDI9IjE0IiB5MT0iMTEiIHkyPSIxMSIvPjwvc3ZnPg==)}.spl-download{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgaGVpZ2h0PSIxNDEuNzMycHgiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDE0MS43MzIgMTQxLjczMiIgd2lkdGg9IjE0MS43MzJweCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTIwLjY3NCwxMjUuMTM4SDIwLjc5M3YxNi41OTRoOTkuODgxVjEyNS4xMzh6IE0xMTkuMDE5LDU4Ljc3NmMtMi41NjEtMi41NjItNi43MTYtMi41NjItOS4yNzUsMEw3Ny4yMSw5MS4zMTJWNi41NjIgICBDNzcuMjEsMi45MzYsNzQuMjY5LDAsNzAuNjQ4LDBjLTMuNjI0LDAtNi41NiwyLjkzNy02LjU2LDYuNTYzdjg0Ljc1TDMxLjk5Miw1OS4yMThjLTIuNTYyLTIuNTY0LTYuNzE1LTIuNTY0LTkuMjc3LDAgICBjLTIuNTY1LDIuNTYyLTIuNTY1LDYuNzE2LDAsOS4yNzlsNDMuMjk0LDQzLjI5M2MwLjE1LDAuMTU0LDAuMzE0LDAuMjk5LDAuNDgxLDAuNDM4YzAuMDc2LDAuMDYyLDAuMTU1LDAuMTEzLDAuMjM0LDAuMTc2ICAgYzAuMDk0LDAuMDY1LDAuMTg2LDAuMTQyLDAuMjc5LDAuMjA2YzAuMDk3LDAuMDYzLDAuMTkyLDAuMTE0LDAuMjg2LDAuMTc0YzAuMDg4LDAuMDU0LDAuMTc0LDAuMTA1LDAuMjY1LDAuMTUzICAgYzAuMSwwLjA1NiwwLjE5OSwwLjEsMC4yOTgsMC4xNDdjMC4wOTcsMC4wNDUsMC4xOSwwLjA5MSwwLjI4MywwLjEzMmMwLjA5OCwwLjA0LDAuMTk2LDAuMDcyLDAuMjk1LDAuMTA1ICAgYzAuMTA0LDAuMDM4LDAuMjA3LDAuMDc4LDAuMzEyLDAuMTA5YzAuMTAxLDAuMDMsMC4xOTcsMC4wNTIsMC4yOTcsMC4wNzdjMC4xMDgsMC4wMjMsMC4yMTQsMC4wNTgsMC4zMjQsMC4wNzggICBjMC4xMTUsMC4wMjEsMC4yMzEsMC4wMzMsMC4zNDYsMC4wNTRjMC4wOTcsMC4wMTUsMC4xOTIsMC4wMzIsMC4yODksMC4wNDJjMC40MywwLjA0MiwwLjg2NSwwLjA0MiwxLjI5NSwwICAgYzAuMS0wLjAxLDAuMTkxLTAuMDI3LDAuMjg5LTAuMDQyYzAuMTE0LTAuMDIxLDAuMjMzLTAuMDI5LDAuMzQ0LTAuMDU0YzAuMTA5LTAuMDIxLDAuMjE3LTAuMDU1LDAuMzI0LTAuMDc4ICAgYzAuMTAyLTAuMDI1LDAuMTk5LTAuMDQ3LDAuMjk5LTAuMDc3YzAuMTA1LTAuMDMxLDAuMjA3LTAuMDcxLDAuMzEyLTAuMTA5YzAuMTAyLTAuMDMsMC4xOTUtMC4wNjIsMC4yOTUtMC4xMDUgICBjMC4wOTYtMC4wNDEsMC4xOTEtMC4wODcsMC4yODMtMC4xMzJjMC4xLTAuMDQ4LDAuMTk5LTAuMDkyLDAuMjk3LTAuMTQ3YzAuMDkxLTAuMDQ4LDAuMTc3LTAuMTA0LDAuMjY0LTAuMTUzICAgYzAuMDk4LTAuMDYsMC4xOTMtMC4xMSwwLjI4Ny0wLjE3NGMwLjA5Ni0wLjA2NCwwLjE4OS0wLjE0MSwwLjI4MS0wLjIwNmMwLjA3Ni0wLjA2MiwwLjE1Ni0wLjExMywwLjIzMy0wLjE3NiAgIGMwLjI0OS0wLjIwNCwwLjQ3OS0wLjQzNywwLjY5NC0wLjY3YzAuMDc2LTAuMDY3LDAuMTU0LTAuMTMxLDAuMjI5LTAuMjAzbDQzLjI5NC00My4yOTYgICBDMTIxLjU4MSw2NS40OTEsMTIxLjU4MSw2MS4zMzcsMTE5LjAxOSw1OC43NzYiLz48L2c+PC9zdmc+);background-size:20px}.spl-theme{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBoZWlnaHQ9IjI0cHgiIHZlcnNpb249IjEuMiIgdmlld0JveD0iMiAyIDIwIDIwIiB3aWR0aD0iMjRweCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMTIsNGMtNC40MTgsMC04LDMuNTgyLTgsOHMzLjU4Miw4LDgsOHM4LTMuNTgyLDgtOFMxNi40MTgsNCwxMiw0eiBNMTIsMThjLTMuMzE0LDAtNi0yLjY4Ni02LTZzMi42ODYtNiw2LTZzNiwyLjY4Niw2LDYgUzE1LjMxNCwxOCwxMiwxOHoiLz48cGF0aCBkPSJNMTIsN3YxMGMyLjc1NywwLDUtMi4yNDMsNS01UzE0Ljc1Nyw3LDEyLDd6Ii8+PC9nPjwvc3ZnPg==)}.spl-play{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSItMC41IC0wLjUgMjUgMjUiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxwb2x5Z29uIGZpbGw9IiNmZmYiIHBvaW50cz0iMTAgOCAxNiAxMiAxMCAxNiAxMCA4Ii8+PC9zdmc+)}.spl-play.on{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSItMC41IC0wLjUgMjUgMjUiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxsaW5lIHgxPSIxMCIgeDI9IjEwIiB5MT0iMTUiIHkyPSI5Ii8+PGxpbmUgeDE9IjE0IiB4Mj0iMTQiIHkxPSIxNSIgeTI9IjkiLz48L3N2Zz4=);animation:pulsate 1s ease infinite}.spl-close{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSIyIDIgMjAgMjAiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bGluZSB4MT0iMTgiIHgyPSI2IiB5MT0iNiIgeTI9IjE4Ii8+PGxpbmUgeDE9IjYiIHgyPSIxOCIgeTE9IjYiIHkyPSIxOCIvPjwvc3ZnPg==)}.spl-next,.spl-prev{top:50%;width:50px;height:50px;opacity:.65;background-color:rgba(0,0,0,.45);border-radius:100%;cursor:pointer;margin-top:-25px;transform:translateX(-100px);background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cG9seWxpbmUgcG9pbnRzPSIxNSAxOCA5IDEyIDE1IDYiLz48L3N2Zz4=);background-size:30px}.spl-prev{left:20px}.spl-next{left:auto;right:20px;transform:translateX(100px) scaleX(-1)}#spotlight.menu .spl-prev{transform:translateX(0)}#spotlight.menu .spl-next{transform:translateX(0) scaleX(-1)}@media (hover:hover){.spl-page~div{cursor:pointer;transition:opacity .2s ease}.spl-next:hover,.spl-page~div:hover,.spl-prev:hover{opacity:1}}@media (max-width:500px){.spl-header div{width:44px}.spl-footer .spl-title{font-size:20px}.spl-footer{font-size:14px}.spl-next,.spl-prev{width:35px;height:35px;margin-top:-17.5px;background-size:15px 15px}.spl-spinner{background-size:30px 30px}}.hide-scrollbars{overflow:hidden!important}"; +var ba=document.getElementsByTagName("head")[0];ba.firstChild?ba.insertBefore(aa,ba.firstChild):ba.appendChild(aa);Object.assign||(Object.assign=function(a,b){for(var c=Object.keys(b),e=0,f;e
";var ia={},ja=document.createElement("video");function ka(a,b,c,e){if("node"!==e)for(var f=Object.keys(c),A=0,w;A.5*(0>a?1:a?-1:0)?eb():db())}function W(a,b){("boolean"===typeof a?a:!R)===!R&&(R=R?clearTimeout(R):1,d(Wa,"on",R),b||ub(R))}function ub(a){wa&&(da(O,function(){g(O,"transition-duration","");g(O,"transform","")}),a&&(g(O,"transition-duration",Ha+"s"),g(O,"transform","translateX(0)")));a&&(R=setTimeout(ib,1E3*Ha))}function X(){Ba&&(Ya=Date.now()+2950,S||(d(p,"menu",!0),Eb(3E3)))} +function Eb(a){S=setTimeout(function(){var b=Date.now();b>=Ya?(d(p,"menu"),S=0):Eb(Ya-b)},a)}function Fb(a){"boolean"===typeof a&&(S=a?S:0);S?(S=clearTimeout(S),d(p,"menu")):X()}function kb(a){ea(a,!0);sa=!0;ta=!1;var b=a.touches;b&&(b=b[0])&&(a=b);ua=qa*v<=u;na=a.pageX;oa=a.pageY;m(L)}function mb(a){ea(a);if(sa){if(ta){if(ua&&ta){var b=(a=r<-(u/7)&&(zu/7&&(1b?r=b:r<-b&&(r=-b),ra*v>pa&&(b=(ra*v-pa)/2,t-=oa-(oa=a.pageY),t>b?t=b:t<-b&&(t=-b)));ta=!0;Z(r,t)}else X()}function cb(a){var b=yb();if("boolean"!==typeof a||a!==!!b)if(b)document[Za]();else p[T]()}function fb(a){"string"!==typeof a&&(a=y?"":Ca||"white");y!==a&&(y&&d(p,y),a&&d(p,a,!0),y=a)} +function V(a){"boolean"===typeof a&&(x=!a);x=1===v&&!x;d(N,"autofit",x);g(N,"transform","");v=1;t=r=0;wb();m(L);Z()}function db(){var a=v/.65;50>=a&&(x&&V(),r/=.65,t/=.65,Z(r,t),Gb(a))}function eb(){var a=.65*v;x&&V();1<=a&&(1===a?r=t=0:(r*=.65,t*=.65),Z(r,t),Gb(a))}function Gb(a){v=a||1;sb()}function gb(){var a=K,b=document.createElement("a"),c=N.src;b.href=c;b.download=c.substring(c.lastIndexOf("/")+1);a.appendChild(b);b.click();a.removeChild(b)} +function bb(a){setTimeout(function(){K.removeChild(p);L=N=P=D=E=C=xa=ya=za=Fa=null},200);d(K,"hide-scrollbars");d(p,"show");cb(!1);qb();history.go(!0===a?-1:-2);Q&&(La.src="");R&&W();N&&xb(N);S&&(S=clearTimeout(S));y&&fb();I&&d(p,I);za&&za()}function xb(a){if(a.g)a.g.appendChild(a),a.g=null;else{var b=a.parentNode;b&&b.removeChild(a);a.src=a.onerror=""}}function hb(a){a&&X();if(1z;z=a;pb(b);return!0}} +function Ib(a){var b=C[z-1],c=b;D={};E&&Object.assign(D,E);Object.assign(D,c.dataset||c);va=D.media;Fa=D.onclick;Ca=D.theme;I=D["class"];Ba=Y("autohide",!0);G=Y("infinite");wa=Y("progress",!0);H=Y("autoslide");Da=Y("preload",!0);Ea=D.buttonHref;Ha=H&&parseFloat(H)||7;y||Ca&&fb(Ca);I&&d(p,I,!0);I&&da(p);if(c=D.control){c="string"===typeof c?c.split(","):c;for(var e=0;e