#76 2025-08-28 11:28:53

MikeM
Учасник
З Київ
Зареєстрований: 2017-11-03
Повідомлень: 184

Re: Регістрова змінна

dimich пише:

...

Дякую за розгорнуту відповідь. Даташит я читав (в моєму про це написано в розділі 14).
Мій працюючий варіант:

SMCR=1; // in setup()

__asm__("sleep/n/t") ; // in loop()

І ніяких бібліотек. Цікаво, що ще пару днів тому я так вже робив. Не запрацювало з-за того, що забув /n/t. Переглянувши бібліотеку зрозумів, у чому був косяк.

Остання редакція MikeM (2025-08-28 11:32:04)

Неактивний

#77 2025-08-28 11:51:27

jokeer
Гість

Re: Регістрова змінна

Не запрацювало з-за того, що забув /n/t.

Не зрозумів роль /n/t

#78 2025-08-28 12:33:45

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 630

Re: Регістрова змінна

MikeM пише:

І ніяких бібліотек.

А SMCR, по-вашому, де визначено? wink На avr-libc і весь ардуіно фреймворк побудований, так що це як раз із бібліотекою. Тільки замість бібліотечної функції чи макроса прямий доступ до регістра. Цілком можна і так, якщо не планується компілювати для контролерів, у яких sleep modes визначаються не через SMCR.

MikeM пише:

Цікаво, що ще пару днів тому я так вже робив. Не запрацювало з-за того, що забув /n/t. Переглянувши бібліотеку зрозумів, у чому був косяк.

Дивно, бо для єдиної інструкції у виразі в asm це не має значення. А для кількох інструкцій без \n була б синтаксична помилка.

jokeer пише:

Не зрозумів роль /n/t

\n для асемблера, бо компілятор спочатку зклеює сусідні строкові літерали, потім передає асемблеру. А асемблеру потрібно розрізняти рядки з мнемоніками. Але для єдиної інструкції це не обовʼязково.
\t для краси, щоби при виводі асемблерного лістингу наступний рядок був з відступом.

Неактивний

#79 2025-09-05 21:57:38

MikeM
Учасник
З Київ
Зареєстрований: 2017-11-03
Повідомлень: 184

Re: Регістрова змінна

Більше тижня нічого не писав, бо дуже ретельно працював над проектом. Схоже, те, що було потрібно, отримав. Вийшло виводити на екран 24 текстових рядків по 16 символів плюс 6 інтервалів. Є ідея, як подвоїти кількість символів в рядку за допомогою зовнішньої мікросхеми. Але реалізацію відклав з огляду на поточну неактуальність.
А от ще одну ідею реалізував і екран у мене тепер кольоровий. Що цікаво, навантаження на процессор практично не зросло.
Дякую усім, хто допомагав.
Найскладнішим виявився такий фрагмент:
У 32-розрядному слові в бітах з 12 по 27 міститься двійковий код 16-розрядного числа з фіксованою крапкою. Старші 9 бітів містять цілу частину, молодші 7 бітів - дробову. Потрібно перетворити його в 6-байтовий код для відображення на екран (по одній двійково-десятковій цифрі в байті).
Задача здається нескладною, але це все треба зробити швидше, ніж за 25 мікросекунд (на 16 МГц 8-бітному Arduino).
Це не прохання про допомогу (у мене вже все працює). Це ідея "задачі вихідного дня" для реально творчіх особистостей. Якщо хтось зацікавиться, спробуйте.
Цікаво, яким буде найменший час.

Остання редакція MikeM (2025-09-05 22:06:41)

Неактивний

#80 2025-09-06 02:26:12

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 630

Re: Регістрова змінна

MikeM пише:

У 32-розрядному слові в бітах з 12 по 27 міститься двійковий код 16-розрядного числа з фіксованою крапкою. Старші 9 бітів містять цілу частину, молодші 7 бітів - дробову. Потрібно перетворити його в 6-байтовий код для відображення на екран (по одній двійково-десятковій цифрі в байті).
Задача здається нескладною, але це все треба зробити швидше, ніж за 25 мікросекунд (на 16 МГц 8-бітному Arduino).

Якщо правильно зрозумів вхідний та вихідний формати, то дві таблиці з десятковими цифрами, 3 * (512 + 128) = 1920 байт флеша. Навіть "в лоб", без низькорівневої оптимізації:

const char PROGMEM intr[512 * 3] = {
    0, 0, 0,
    0, 0, 1,
    ...
    5, 1, 0,
    5, 1, 1
}; 

const char PROGMEM frac[128 * 3] = {
    0, 0, 0, 
    0, 0, 8,
    ...
    9, 8, 4,
    9, 9, 2
};

char out[6];

void convert(uint32_t n)
{
    char *dst = out;
    const char *src = intr + 3*((n >> 19) & 511);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
    src = frac + 3*((n >> 12) & 127);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
}

виходить щось біля сотні тактів, десь 7 мкс.
Звісно, BCD можна упакувати. Тоді таблиці будуть менші, але виконання трохи довшим.

Остання редакція dimich (2025-09-06 10:19:40)

Неактивний

#81 2025-09-06 10:57:00

jokeer
Гість

Re: Регістрова змінна

Прикольно wink я заходився гуглити швидкий алгоритм ділення на 5 wink але там дофіга асемблера,  і враховувати такти не дуже й хотілось

#82 2025-09-06 12:00:16

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 630

Re: Регістрова змінна

dimich пише:

Звісно, BCD можна упакувати. Тоді таблиці будуть менші, але виконання трохи довшим.

А якщо правильно упакувати, то і таблиці в півтора раза менші, і виконання навіть швидше. Має вийти десь 5.5 мкс.

const uint16_t PROGMEM intr[512] = { 0x000, 0x001, ... 0x510, 0x511 };
const uint16_t PROGMEM frac[128] = { 0x000, 0x008, ... 0x984, 0x992 };
char out[6];

void convert(uint32_t n)
{
    char *dst = out;
    uint16_t d;
    d = pgm_read_word(intr + ((n >> 19) & 511));
    *dst++ = d >> 8;
    *dst++ = (d >> 4) & 0xf;
    *dst++ = d & 0xf;
    d = pgm_read_word(frac + ((n >> 12) & 127));
    *dst++ = d >> 8;
    *dst++ = (d >> 4) & 0xf;
    *dst = d & 0xf;
}

Неактивний

#83 2025-09-06 15:06:33

MikeM
Учасник
З Київ
Зареєстрований: 2017-11-03
Повідомлень: 184

Re: Регістрова змінна

Класний варіант. Звичайно, обробки, швидше ніж таблична, не існує.
Однак, не варто було одразу викладати код. JOKEERу весь кайф обламали.

Неактивний

#84 2025-09-06 16:58:24

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 630

Re: Регістрова змінна

MikeM пише:

Звичайно, обробки, швидше ніж таблична, не існує.

Та не завжди. Залежить від алгоритму та особливостей архітектури. Хоча, спеціалізовані інструкції, по суті, на таких же "таблицях" реалізовані, тільки вони містяться на самому кристалі.
Звісно, в загальному випадку нічого швидше за O(1) не існує, але в конкретних випадках бувають нюанси. В мультизадачному середовищі взагалі, ще питання, що краще: виконати кілька додаткових інструкцій, чи лазити в таблицю через спільний кеш.

MikeM пише:

Однак, не варто було одразу викладати код. JOKEERу весь кайф обламали.

Вибачте, не хотів. Здавалось очевидним. Але там є ще простір для подальшої оптимізації wink

Неактивний

#85 2025-09-11 09:41:52

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 161

Re: Регістрова змінна

https://www.rcgroups.com/forums/showthread.php?1473207-Diy-osd-(Arduino-and-opensource) - тут чувак досить сильно упоровся в цю тему з формуванням OSD на ардуїні.

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму