но вот беда... не могу посимвольно читать строку... Что-то тут не так:
Код:
for(i=0;i<strlen(Font[C].Lines);i++) { if (Font[C].Lines[i]!="|") { } }
Буквально формально но длина строчки будет пере-strlen-иться на каждой итерации цикла. Оптимизатор, конечно, дремать не будет - но иные пожилые обитатели сего места могут и инфаркт схватить почём зря увидев такое. Но это лирика и оффтоп. Обращение-же ваше к i-тому элементу строки Lines по индексу вполне легально - Lines это указатель и его можно читать как кому нравится - хоть массивно, хоть адресно-арифметично. Но, - Сравниваете вы с адресом строкового литерала "|" а не с байтом 0х7C как задумывалось. Для символьных литералов нужно использовать одиночные кавычки. В качестве мелкого пятничного издевательства вот вам немножко Ъ-шных пере-интерпретаций вашей идеи. Для разминки.
Код:
char* p = NULL; for (p = Font[C].Lines; *p; p++) { if (*p != '|') { } }
Но подход ваш зело эклектичный, и знание дельфи никак не освобождает от необходимости понимания сути творимых вещей. Так строчки в С - это последовательности байтов, которые завершаются нулём. И strlen в общем случае будет тупо перебирать их от начала до конца - а вы это в условие цикла вставили - видимо чтобы МК не скучал в главном цикле программы. А "|" это строковая константа и состоит она из двух байтов 0x7C 0x00. И тип у этой константы const char*. А операция взятия элемента массива (в нашем случае строки char-ов) по индексу возвращает нам значение типа char. А вы его сравниваете с const char* - а для компилятора это всё равно как вам на завтрак огурцы солёные с молочком кто предложит, чтобы день прошёл не зазря.
_________________ Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR!
храниить шрифт в текстовом виде?! до этого даже в Майкрософте не додумались!
никто так не делает, да, но емнип патент на такое безумство таки есть)
Shrike, у вас в чем конкретно проблема? Первоначально - в ваших строках вида "010516364541301001|0541" все эти "01", "05", "16" и так далее по задумке должны соответстовать числам 1, 5, 16, или таки по счастливой случайности являются какими-никакими корректными строковыми представлениями двухбайтовых чисел?)
Зарегистрирован: Пт мар 02, 2018 16:31:19 Сообщений: 7
Рейтинг сообщения:0
Спасибо всем, кто откликнулся и оказал помощь!
"01", "05", "16" это пара координат точек полилиний: (x=0;y=1); (x=0;y=5); (x=1;y=6) ... по оси х больше 4 не бывает, по у - не более 7. Шрифт 4х6 и хвосты у некоторых символов до 7 На глубокое изучение языка Си просто нет времени, для хобби "и так сойдет" =) Задумку реализовать получилось, в качестве примера приведу фото дисплея с парочкой символов в оригинальном масштабе и в масштабе 7.5 Код приводить не буду, дабы, как написал Siarzhuk, "пожилые обитатели сего места могут и инфаркт схватить почём зря увидев такое" =)))
Следующий этап - антиалайзинг. Если интересно, могу выложить результаты.
Задумку реализовать получилось, в качестве примера приведу фото дисплея с парочкой символов в оригинальном масштабе и в масштабе 7.5
Думаю не я один сейчас злорадно ухмыльнулся, зная как оно там у вас "оптимально" устроено, в желании задать вопрос: -"Кабы, барин, видео посмотреть. А фоточками сыт не будешь, вестимо."
_________________ Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR!
Зарегистрирован: Пт мар 02, 2018 16:31:19 Сообщений: 7
Рейтинг сообщения:0
Уважаемые гуру! Я прекрасно понимаю, что у меня дико криво реализован алгоритм хранения векторного шрифта, впрочем, как и его прорисовка. Я понимаю, что по хорошему пару координат нужно хранить в 1 байте. Но, мне крайне тяжело и долго нужно будет разбираться в том, как создать тип данных в виде структуры с динамическим массивом и этот тип назначить статическому массиву. Сама сложность для меня состоит в самом понимании где и когда нужно использовать указатель, выделять память, освобождать... При всем этом самого синтаксиса не знаю... Ну да ладно, будет время - разберемся. Правда в том, что действительно времени может и не быть, но возникнет необходимость.
По поводу видео: могу конечно записать, только что именно? пока у меня реализовано 25 символов и функция void DrawChar(uint8_t C, uint16_t X, uint16_t Y, float scale), где C - индекс символа.
Добавлено after 11 minutes: Решил все же показать код, только рассматривайте его как анекдот, не принимайте близко к сердцу =)
Зачем паковать байт? Байт он всегда байт - как его ни пакуйте - а sizeof(t_point) в конкретном случае будет 1. Биты 0-2 отводятся под x, а 3-5 - под y. Биты-же 6,7 остаются неиспользуемы при любом раскладе кроме явного их указания в качестве поля(пары полей) размером 2 бита (либо по биту). Поле размером 3 бита займёт уже 0-2 биты следующего байта.
Код:
struct t_point { unsigned char x : 3; unsigned char y : 3; unsigned char z : 3; };
Для того-же, чтобы все биты лежали плотнячком - придется объявлять базовый тип поля пошире - т.е. unsigned short как минимум. Но, любителей накладывать такие "широкие" битовые маски на сырые данные прилетевшие из внешнего мира ждут некоторые сюрпризы - особенно на "остроконечниковых" (low endian) платформах. Да даже уже и в нашем примере пытливый глаз наверняка обнаружил некоторую странность - отчего-то "младшие" x,y лежат перед "старшим" z, не так-ли?
А вот вариант с short -ом:
Код:
struct t_point { unsigned short x : 3; unsigned short y : 3; unsigned short z : 3; };
union uu { unsigned char bb[2]; unsigned short s; } u = { 0 };
Биты уплотнились как надо - но в байтовом массиве по прежнему "бардачат", а вот как unsigned short всё прекрасно - потому как собирал я этот примерчик на LE платформе.
Грустные выводы - не все возможные комбинации можно представить в битовых полях, а для low endian придётся порой ещё и байты в исходных данных переставлять (для кайловских ARM тулчейнов, кстати, есть интриниксы _REV16, _REV32)
Но, мне крайне тяжело и долго нужно будет разбираться в том, как создать тип данных в виде структуры с динамическим массивом и этот тип назначить статическому массиву.
С - это высокоуровневый ассемблер - понимая как компилятор с компоновщиком строят образ программы вы будет знать как работает железяка. Без всякой магии. Дело стоящее - не исключайте для себя такую возможность. :-D
Всё вышеприведенное объявляется в глобальной области (не в функциях!) - и вся работа будет сделана компилятором - функции DrawChar остаётся только воспользоваться уже набитым массивом данных. И не забудьте терминировать все данные символов байтом EOL - иначе оно отрисует вам содержимое всей памяти аж до случайно встреченного символа с установленным верхним битом.
Код:
void DrawChar(uint8_t C, uint16_t X, uint16_t Y, float scale) { t_point* p0 = NULL; t_point* p = NULL;
for (p0 = Font[C].Line, p = Font[C].Line + 1; 0 == p->eol; p0 = p, p++) { if (0 != p->brk ) continue;
drawLine( X + p0->x * scale - k * scale, Y + p0->y * scale - k * scale, X + p->x * scale - k * scale, Y + p->y * scale - k * scale, Color565(255, 255, 255)); } }
По поводу видео: могу конечно записать, только что именно?
Не заморачивайтесь - подкалывал я вас. Скорость работы программы оценивается [тупым] юзером по времени отклика системы на его хотелки - и если шрифт рисуется с заметным анимационным эффектом - это медленная система с его [тупой] точки зрения. А если глаз не замечает - то и чёрт с ним - занимается ли там МК парсингом ваших строковых литералов на лету или просто хомячит инструкции в бесконечности главного цикла - всё едино лепота.
Решил все же показать код, только рассматривайте его как анекдот, не принимайте близко к сердцу =)
Как по мне так это было правильное решение с вашей стороны. Да, и ещё по описанию вектора отрисовки символа - идею с размещением х и y в полубайтах для большей наглядности вы поняли, кстати?
_________________ Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR!
Зачем паковать байт? Байт он всегда байт - как его ни пакуйте - а sizeof(t_point) в конкретном случае будет 1.
В вашем конкретном случае будет. А в общем случае - нет. Поэтому если у вас есть структура и вы хотите минимизировать размер занимаемой ею памяти, то всегда следует включать выравнивание к одному байту.
Стандарт не определяет: — The alignment of the addressable storage unit allocated to hold a bit-field И отдает на откуп компиляторам: — Whether a ‘‘plain’’ int bit-field is treated as a signed int bit-field or as an unsigned int bit-field — Allowable bit-field types other than _Bool, signed int, and unsigned int — Whether atomic types are permitted for bit-fields — Whether a bit-field can straddle a storage-unit boundary — The order of allocation of bit-fields within a unit — The alignment of non-bit-field members of structures. This should present no problem unless binary data written by one implementation is read by another.
TM1638_STB_LOW(); TM1638_write_byte(TM1638_CMD_READ_KEYS); // _delay_us(2); // Минимально необходимая по даташиту задержка 2 мкс - можно убрать, все равно есть задержка после поднятия CLK в процедуре записи байта #ifdef USE_USI_FOR_TM1638 half_spi_init_receive(); // Init SPI driver as RECEIVED master. _delay_us(100); #else TM1638_DIO_INPUT(); // Установим ногу на вход !!! #endif
for (keys_code = 0; keys_code < 4; keys_code++) // Будем читать 4 байта состояний кнопок { for (key_number = 0; key_number < 8; key_number++) // Перебор всех кнопок этого байта { TM1638_CLK_LOW(); _delay_us(TM1638_DELAY_US); TM1638_CLK_HIGH();
if (TM1638_DIO_READ()) // Если есть нажатая кнопка { keys[keys_code] |= (1<<key_number); // Устанавливаем в ЭТОМ байте бит ЭТОЙ кнопки }
_delay_us(TM1638_DELAY_US); } } #endif
TM1638_STB_HIGH();
#ifdef USE_USI_FOR_TM1638 half_spi_reinit_transmit(); // Init SPI driver as TRANSMIT master.
#else TM1638_DIO_OUTPUT(); // Вернем ногу на выход !!! #endif
_delay_us(TM1638_DELAY_US);
TM1638_send_comm(TM1638_CMD_SET_DATA | TM1638_SET_DATA_F_ADDR); // Установка режима работы - Запись в индикатор, Фиксированный адрес
_delay_us(TM1638_DELAY_US);
keys_code = keys[0] | (keys[1]<<1) | (keys[2]<<2) | (keys[3]<<3); // Собираем состояние всех кнопок в 1 байт (0 и 4 бит каждого из 4 принятых байт)
#ifdef RETURN_KEY_NUMBER if (keys_code) // Если нажата кнопка - вычисляем ее номер (Внимание, будет передана только 1, самая младшая кнопка !!!) { for (key_number = 0; key_number < 8; key_number++, keys_code >>=1) { if (keys_code & 0x01) // Если 0 бит установлен, найдена нажатая кнопка (Внимание, первой будет найдена кнопка из младшего бита) { return key_number+1; // Возвращаем порядковый номер первой найденой нажатой кнопки } } } #endif
return keys_code; // Возвращаем состояние всех кнопок }
В вашем конкретном случае будет. А в общем случае - нет. Поэтому если у вас есть структура и вы хотите минимизировать размер занимаемой ею памяти, то всегда следует включать выравнивание к одному байту.
К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром если структура данных жёстко определена не нами да в случае очень уж сиротских ресурсов у нас - когда в .data уже 0, а в .text ещё место есть и можно заколоть корову эффективности, чтобы вымолить пару байт на данные (битовые поля в ту же кассу кстати работают иногда). Ну и из эстетических соображений - зело уродски выглядит как на мой взгляд.
Хотелось бы увидеть пример такого случая, при котором sizeof(t_point) будет не равен 1. Можете привести ?
Любая структура, в которую вы кроме имеющихся битовых полей добавите дополнительные данные. В вашем частном случае структура имеет размер 1 байт. Но если потом будут добавлены дополнительные элементы (а это часто требуется - скажем, добавят цвет), то может проявиться выравнивание структур и структура окажется не минимального достижимого размера. Поэтому стоит всегда дописывать указание компилятору на выравнивание структур.
Цитата:
Размер структуры = 1 байт. Куда дальше минимизировать ?
Это он сейчас один байт. Программы имеют свойство развиваться и структуры имеют свойство изменяться. Бывает даже, что копируются структуры из старой программы и дорабатываются в новой. И вот тогда размер не будет один байт. А вот насколько он окажется больше ожидаемого зависит от выравнивания. При этом вы можете даже и не заметить, что потеряли достаточно много памяти всего лишь добавив к этой структуре, например, 32 битный цвет точки и создав штук 100 таких структур (800-500=300 байт потеряно впустую). #pragma pack(1) спасёт от этой проблемы.
Карма: 90
Рейтинг сообщений: 1443
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4609 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
da-nie писал(а):
Это он сейчас один байт.
Аlex писал(а):
Вашу пару можно сократить до 1 байта, при таких условиях.
Ежу понятно, что если в структуру добавить ещё поля, она увеличится в размерах. Но почему её в данном виде нужно паковать, Вы нам секрет так и не открыли.
К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром
Не только. Если у вас, например, на atmega8 есть крошечное ОЗУ, то создав массив структур вы потеряете довольно много памяти.
Цитата:
Ну и из эстетических соображений - зело уродски выглядит как на мой взгляд.
Если для вас главное - минимизация размера памяти, занимаемых структурой, то этот подход избавит от незамеченного увеличения размера структуры только потому, что вы что-то в неё добавили.
Цитата:
Не опаснее указателя.
Опаснее. Указатель редко используют не по назначению (скажем, разность указателей брать весьма опасно, но так, обычно, и не делают). Это хорошо, когда процессор достаточно обычный. А у меня вот валяется 1967ВЦ1Т. У него в компиляторе байт 32-битный.
Цитата:
Ежу понятно, что если в структуру добавить ещё поля, она увеличится в размерах. Но почему её в данном виде нужно паковать, Вы нам секрет так и не открыли.
Потому что если вы добавите туда ещё поле с unsigned long Color, то размер будет не 5, а 8 без #pragma pack(1). И 5 с #pragma pack(). А в конкретном виде, как у вас, её нужно выравнивать потому, чтобы в дальнейшем избежать сюрпризов. Это просто рекомендация на будущее, чтобы не было потом мучительно больно.
Не стоит этого делать всегда, не говорите ерунды. Упаковывать структуры нужно только в крайне необходимых ситуациях.
У вас задача стоит в уменьшении размера памяти. Вреда от #pragma pack(1) в вашем случае у вас всё равно не будет (он не повлияет на ваш вариант, но может повлиять при модификации структуры).
Добавлено after 48 seconds:
Цитата:
О каких сюрпризах идёт речь ? То, что структура займёт больше памяти ?
Да. В условиях этой памяти в 1 кб это может быть очень важно.
P.S. Соврал, не 1967ВЦ1Т - тоже ВЦ, но по-другому как-то называется. Аналог процессора середины 80-х. Мерзость, короче.
Карма: 90
Рейтинг сообщений: 1443
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4609 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
Вы увиливаете от темы, ссылаясь на "потом". Не будет у человека никаких "потом". У него есть конкретные условия, при которых ему был предложен вариант ужать координаты до 1 байта, вместо им используемых 2-ух. И почему, в конкретном случае (!), без #pragma pack это должно не получиться ("Иначе фокус может не получиться") - до сих пор остаётся загадкой.
Добавлено after 6 minutes 49 seconds: PS: Не подумайте ничего плохого, я этот диалог развил не ради того, чтобы пообщаться от безделия. Просто Вас читают люди, и совет "нужно всегда упаковывать", чтобы потом не нарваться на какие-то там грабли - очень плохой. Нужно говорить "никогда не упаковывайте без надобности" !
И почему, в конкретном случае (!), без #pragma pack это должно не получиться ("Иначе фокус может не получиться") - до сих пор остаётся загадкой.
Читайте внимательнее - "фокус может не получиться". Я не утверждал, что в конкретном случае не получится.
Цитата:
Вы увиливаете от темы, ссылаясь на "потом".
Вообще-то, жизненный цикл программы это самое "потом" предполагает всегда. Знаете, как часто могут перетряхиваться самые простые структуры данных в программе? Добавили одно - убрали другое. Поменяли дисплей на с большим разрешением - не хватает старого размера битового поля для координат. И так далее. Ещё раз для тех, кому обедню два раза не служат: хорошим тоном при желании минимизировать объём структуры будет указание выравнивания к 1 байту с самого начала. Иначе потом, по мере развития проекта, может оказаться, что память уже исчерпана, а вы и не заметили, почему.
Цитата:
PS: Не подумайте ничего плохого, я этот диалог развил не ради того, чтобы пообщаться от безделия. Просто Вас читают люди, и совет "нужно всегда упаковывать", чтобы потом не нарваться на какие-то там грабли - очень плохой. Нужно говорить "никогда не упаковывайте без надобности" !
А я подумаю именно плохое. Потому что у меня такой коллега есть - он всегда отвечает и ругается на то, чего ему никто не говорил и он по сути просто так понял, домыслив часть сам. Совет был дан для случая, когда вам нужно минимизировать объём занимаемой памяти - разве вы не этим занимались? А так - выравнивание ни к чему плохому не приведёт, кроме как к возможному снижению производительности.
К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром если структура данных жёстко определена не нами да в случае очень уж сиротских ресурсов у нас - когда в .data уже 0, а в .text ещё место есть и можно заколоть корову эффективности, чтобы вымолить пару байт на данные.
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения