но вот беда... не могу посимвольно читать строку... Что-то тут не так:
Код:
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
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4590 Откуда: Планета Земля
Рейтинг сообщения: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
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4590 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
Вы увиливаете от темы, ссылаясь на "потом". Не будет у человека никаких "потом". У него есть конкретные условия, при которых ему был предложен вариант ужать координаты до 1 байта, вместо им используемых 2-ух. И почему, в конкретном случае (!), без #pragma pack это должно не получиться ("Иначе фокус может не получиться") - до сих пор остаётся загадкой.
Добавлено after 6 minutes 49 seconds: PS: Не подумайте ничего плохого, я этот диалог развил не ради того, чтобы пообщаться от безделия. Просто Вас читают люди, и совет "нужно всегда упаковывать", чтобы потом не нарваться на какие-то там грабли - очень плохой. Нужно говорить "никогда не упаковывайте без надобности" !
И почему, в конкретном случае (!), без #pragma pack это должно не получиться ("Иначе фокус может не получиться") - до сих пор остаётся загадкой.
Читайте внимательнее - "фокус может не получиться". Я не утверждал, что в конкретном случае не получится.
Цитата:
Вы увиливаете от темы, ссылаясь на "потом".
Вообще-то, жизненный цикл программы это самое "потом" предполагает всегда. Знаете, как часто могут перетряхиваться самые простые структуры данных в программе? Добавили одно - убрали другое. Поменяли дисплей на с большим разрешением - не хватает старого размера битового поля для координат. И так далее. Ещё раз для тех, кому обедню два раза не служат: хорошим тоном при желании минимизировать объём структуры будет указание выравнивания к 1 байту с самого начала. Иначе потом, по мере развития проекта, может оказаться, что память уже исчерпана, а вы и не заметили, почему.
Цитата:
PS: Не подумайте ничего плохого, я этот диалог развил не ради того, чтобы пообщаться от безделия. Просто Вас читают люди, и совет "нужно всегда упаковывать", чтобы потом не нарваться на какие-то там грабли - очень плохой. Нужно говорить "никогда не упаковывайте без надобности" !
А я подумаю именно плохое. Потому что у меня такой коллега есть - он всегда отвечает и ругается на то, чего ему никто не говорил и он по сути просто так понял, домыслив часть сам. Совет был дан для случая, когда вам нужно минимизировать объём занимаемой памяти - разве вы не этим занимались? А так - выравнивание ни к чему плохому не приведёт, кроме как к возможному снижению производительности.
К байту, а мы речь ведём о битах. И включать его следует не всегда а лишь тогда когда данный эффект требуется - при обмене с внешним миром если структура данных жёстко определена не нами да в случае очень уж сиротских ресурсов у нас - когда в .data уже 0, а в .text ещё место есть и можно заколоть корову эффективности, чтобы вымолить пару байт на данные.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения