Обсуждаем контроллеры компании Atmel.
Ответить

Re: Преобразование байта в три десятичные цифры

Сб июн 29, 2019 07:40:29

не обязательно, что это будут ЧАСЫ.

Я про часы говорил, как про особый случай. Только для часов С АВТОНОМНЫМ ПИТАНИЕМ имеет смысл сокращение КОЛИЧЕСТВА МАШЦИКЛОВ на такое преобразование. Каждый машинный цикл - это микродоза энергии от источника. То есть часы должны в основном находится в SLEEP-е. Тогда время работы от источника будет определяться саморазрядом этого источника.

Re: Преобразование байта в три десятичные цифры

Сб июн 29, 2019 11:54:32

да понял я тебя. но это очень особый случай, когда нужно экономить питания.
а я рассказал про самый общий случай, когда экономить питание не надо и спешить некуда.

Re: Преобразование байта в три десятичные цифры

Сб июн 29, 2019 21:33:57

Раскурил я предложенную выше статью, а именно раздел 5 "Деление на 10 сдвигами и сложениями". Пошаманив, придумал код для деления байта с остатком на 10 со своими собственными оптимизациями. В частности, корректировку остатка и частного я перенёс в середину процедуры до вычисления остатка, поэтому корректировать надо только частное. Это позволяет сэкономить 2, а то и все 4 такта процессора.

Спойлер
Код:
;==============
.def    val     =   r16
.def    rem     =   r17
.def    tmp     =   r18
;==============
                ;   Процедура осуществляет деление байта на 10 с остатком
                ;   Размер: 38 байт
                ;   Время: 19 тактов
                ;   Регистры: 3 штуки
                ldi     val,    0xAB    ;   Исходная величина
                mov     rem,    val     ;   Подготовка к вычислению остатка
                lsr     val             ;   Рассчёт
                mov     tmp,    val     ;       целой
                lsr     tmp             ;       части
                add     val,    tmp     ;       произведения
                mov     tmp,    val     ;       величины
                swap    tmp             ;       0.8 (10) = 0.1100 1100 1100... (2)
                andi    tmp,    0x0F    ;       на исходный
                add     val,    tmp     ;       байт
                inc     val             ;   Коррекция рассчитанного произведения.
                sbrc    val,    7       ;       Эти две строчки коррекции можно
                inc     val             ;       убрать, если исходный байт <= 169
                andi    val,    0xF8    ;   Искомое частное, умноженное на 8
                sub     rem,    val     ;   Вычисление искомого
                lsr     val             ;       остатка (вычитание)
                lsr     val             ;       одновременно
                sub     rem,    val     ;       с искомым частным
                lsr     val             ;       (деление на 8)
                ;   Конец процедуры

Re: Преобразование байта в три десятичные цифры

Вс июн 30, 2019 13:05:42

Итак, процедуры байт в строку файнал эдишн. С сохранением в оперативку (как заказывали). Три варианта (дабл-дабл в пролёте за неадекватностью).

Табличный метод
Размер: 142 байта
Время: 22...26 тактов
Регистры: 2 штуки + Y + Z
Спойлер
Код:
;==============
.def    tmp1    =   r16
.def    tmp2    =   r17
;==============
                ;   Процедура преобразует байт в строку цифр
                ;       табличным методом и сохраняет её в памяти
                ;   Размер: 142 байта
                ;   Время: 22...26 тактов
                ;   Регистры: 2 штуки + Y + Z
                ldi     ZL,     0x63    ;   Величина, преобразуемая в десятичный вид
                ldi     ZH,     HIGH(2 * t10div)    ;   Таблица разложения чисел 0..99
                ldi     YH,     0x00    ;   Адрес в ОЗУ
                ldi     YL,     0x60    ;       для сохранения результата
                clr     tmp1            ;   Инициализация первой цифры
                subi    ZL,     0x64    ;   Определение
                brcs    branch          ;       первой
                inc     tmp1            ;       цифры
                subi    ZL,     0x64    ;       байта
                brcs    branch          ;       методом
                inc     tmp1            ;       последовательных
                subi    ZL,     0x64    ;       вычитаний
branch:         subi    ZL,     0x9C    ;       величины 100
                st      Y+,     tmp1    ;   Сохранение 1-ой цифры
                lpm     tmp1,   Z       ;   Загрузка десятичного представления остатка
                mov     tmp2,   tmp1    ;   Разделение
                swap    tmp1            ;       остатка на две
                andi    tmp1,   0x0F    ;       десятичные
                andi    tmp2,   0x0F    ;       цифры
                st      Y+,     tmp1    ;   Сохранение 2-ой цифры
                st      Y+,     tmp2    ;   Сохранение 3-ей цифры
                ;   Конец процедуры
;==============
;   Таблица преобразования величин диапазона 0..99 в десятичные цифры
.org    0x0300
t10div:     .dw 0x0100,0x0302,0x0504,0x0706,0x0908,0x1110,0x1312,0x1514,0x1716,0x1918
            .dw 0x2120,0x2322,0x2524,0x2726,0x2928,0x3130,0x3332,0x3534,0x3736,0x3938
            .dw 0x4140,0x4342,0x4544,0x4746,0x4948,0x5150,0x5352,0x5554,0x5756,0x5958
            .dw 0x6160,0x6362,0x6564,0x6766,0x6968,0x7170,0x7372,0x7574,0x7776,0x7978
            .dw 0x8180,0x8382,0x8584,0x8786,0x8988,0x9190,0x9392,0x9594,0x9796,0x9998
;==============

Метод деления на 10 сдвигами и сложением
Размер: 66 байт
Время: 36 тактов
Регистры: 3 штуки + Y
Спойлер
Код:
;==============
.def    val     =   r16
.def    tmp1    =   r17
.def    tmp2    =   r18
;==============
                ;   Процедура преобразует байт в строку цифр методом деления на 10
                ;       с остатком сдвигами и сложениями и сохраняет её в памяти
                ;   Размер: 66 байт
                ;   Время: 36 тактов
                ;   Регистры: 3 штуки + Y
                ldi     val,    0xC7    ;   Величина, преобразуемая в десятичный вид
                ldi     YH,     0x00    ;   Адрес в ОЗУ
                ldi     YL,     0x60    ;       для сохранения результата
                clr     tmp1            ;   Инициализация первой цифры
                cpi     val,    0x64    ;   Определение
                brcs    PC+2            ;       первой
                inc     tmp1            ;       цифры
                brcs    PC+2            ;       байта
                subi    val,    0x64    ;       методом
                cpi     val,    0x64    ;       последовательных
                brcs    PC+2            ;       вычитаний
                inc     tmp1            ;       из него
                brcs    PC+2            ;       величины
                subi    val,    0x64    ;       100
                st      Y+,     tmp1    ;   Сохранение 1-ой цифры
                ;   Деление с остатком на 10
                mov     tmp1,   val     ;   Подготовка к вычислению остатка
                lsr     val             ;   Расчёт
                mov     tmp2,   val     ;       целой
                lsr     tmp2            ;       части
                add     val,    tmp2    ;       произведения
                mov     tmp2,   val     ;       величины
                swap    tmp2            ;       0.8 (10) = 0.1100 1100 1100... (2)
                andi    tmp2,   0x0F    ;       на исходный
                add     val,    tmp2    ;       байт
                inc     val             ;   Коррекция рассчитанного произведения
                andi    val,    0xF8    ;   Искомое частное, умноженное на 8
                sub     tmp1,   val     ;   Вычисление искомого
                lsr     val             ;       остатка (вычитание)
                lsr     val             ;       одновременно
                sub     tmp1,   val     ;       с искомым частным
                lsr     val             ;       (деление на 8)
                st      Y+,     val     ;   Сохранение 2-ой цифры
                st      Y+,     tmp1    ;   Сохранение 3-ей цифры
                ;   Конец процедуры
;==============

Метод циклов с вычитаниями
Размер: 36 байт
Время: 19...69 тактов
Регистры: 2 штуки + Y
Спойлер
Код:
;==============
.def    val     =   r16
.def    tmp     =   r17
;==============
                ;   Процедура преобразует байт в строку цифр методом последовательных
                ;       вычитаний степеней 10 в циклах и сохраняет её в памяти
                ;   Размер: 36 байт
                ;   Время: 19...69 тактов
                ;   Регистры: 2 штуки + Y
                ldi     val,    0xC7    ;   Величина, преобразуемая в десятичный вид
                ldi     YH,     0x00    ;   Адрес в ОЗУ
                ldi     YL,     0x60    ;       для сохранения результата
                clr     tmp             ;   Инициализация 1-ой цифры
loop100:        subi    val,    0x64    ;   Цикл вычитания 100
                brcs    loop100end      ;   Конец цикла, если остаток был меньше 100
                inc     tmp             ;   Инкремент 1-ой цифры
                rjmp    loop100         ;   Повтор цикла
loop100end:     subi    val,    0x9C    ;   Коррекция остатка
                st      Y+,     tmp     ;   Сохранение 1-ой цифры
                clr     tmp             ;   Инициализация 2-ой цифры
loop10:         subi    val,    0x0A    ;   Цикл вычитания 10
                brcs    loop10end       ;   Конец цикла, если остаток был меньше 10
                inc     tmp             ;   Инкремент 2-ой цифры
                rjmp    loop10          ;   Повтор цикла
loop10end:      subi    val,    0xF6    ;   Коррекция остатка
                st      Y+,     tmp     ;   Сохранение 2-ой цифры
                st      Y+,     val     ;   Сохранение 3-ей цифры
                ;   Конец процедуры
;==============

Лично мне нравится метод деления на 10 с остатком. Во-первых за константное время выполнения, а во-вторых за неординарное битовое шаманство. =D Надо бы попробовать реализовать деление на 10 для двух и трёх байт.

Re: Преобразование байта в три десятичные цифры

Вс июн 30, 2019 15:06:11

B@R5uk писал(а):мне нравится метод деления на 10 с остатком. Во-первых за константное время выполнения
ты для примера взял число 199, меньше 200. а число может быть и 255. и для всего диапазона чисел в одном байте не будет константного времени.

Re: Преобразование байта в три десятичные цифры

Вс июн 30, 2019 16:22:02

не будет константного времени.
Чего это вдруг? Условные переходы в начале действуют как команды SBRC/SBRS, и программа выполняется линейно. И потом, в симуляторе я тестил не только одно значение байта.

Re: Преобразование байта в три десятичные цифры

Пн июл 01, 2019 11:58:34

Когда нужно очень быстро преобразовать байт. Вариант полного табличного преобразования для TIC107. 23 такта и готово.
Спойлер
Код:
SIMVOL:
   LDI   ZH,HIGH(T_ZNAK*2)
   LDI   ZL,LOW(T_ZNAK*2)

   CLR   R1
   LDS   R2,$70   ; преобразуемое значение

   LSL   R2
   ROL   R1
   LSL   R2
   ROL   R1      ; R1,R2x4

   ADD   ZL,R2
   ADC   ZH,R1

   LPM   R5,Z+
   LPM   R6,Z+
   LPM   R7,Z+
   LPM   R8,Z

   RJMP   SIMVOL
;*************************************************
T_ZNAK:
   .DB   $20,$20,$20,$B0
   .DB   $20,$20,$20,$B1
   .DB   $20,$20,$20,$B2
   .DB   $20,$20,$20,$B3
   .DB   $20,$20,$20,$B4
   .DB   $20,$20,$20,$B5
   .DB   $20,$20,$20,$B6
   .DB   $20,$20,$20,$B7
   .DB   $20,$20,$20,$B8
   .DB   $20,$20,$20,$B9

   .DB   $20,$20,$B1,$B0
   .DB   $20,$20,$B1,$B1
   .DB   $20,$20,$B1,$B2
   .DB   $20,$20,$B1,$B3
   .DB   $20,$20,$B1,$B4
   .DB   $20,$20,$B1,$B5
   .DB   $20,$20,$B1,$B6
   .DB   $20,$20,$B1,$B7
   .DB   $20,$20,$B1,$B8
   .DB   $20,$20,$B1,$B9

   .DB   $20,$20,$B2,$B0
   .DB   $20,$20,$B2,$B1
   .DB   $20,$20,$B2,$B2
   .DB   $20,$20,$B2,$B3
   .DB   $20,$20,$B2,$B4
   .DB   $20,$20,$B2,$B5
   .DB   $20,$20,$B2,$B6
   .DB   $20,$20,$B2,$B7
   .DB   $20,$20,$B2,$B8
   .DB   $20,$20,$B2,$B9

   .DB   $20,$20,$B3,$B0
   .DB   $20,$20,$B3,$B1
   .DB   $20,$20,$B3,$B2
   .DB   $20,$20,$B3,$B3
   .DB   $20,$20,$B3,$B4
   .DB   $20,$20,$B3,$B5
   .DB   $20,$20,$B3,$B6
   .DB   $20,$20,$B3,$B7
   .DB   $20,$20,$B3,$B8
   .DB   $20,$20,$B3,$B9

   .DB   $20,$20,$B4,$B0
   .DB   $20,$20,$B4,$B1
   .DB   $20,$20,$B4,$B2
   .DB   $20,$20,$B4,$B3
   .DB   $20,$20,$B4,$B4
   .DB   $20,$20,$B4,$B5
   .DB   $20,$20,$B4,$B6
   .DB   $20,$20,$B4,$B7
   .DB   $20,$20,$B4,$B8
   .DB   $20,$20,$B4,$B9

   .DB   $20,$20,$B5,$B0
   .DB   $20,$20,$B5,$B1
   .DB   $20,$20,$B5,$B2
   .DB   $20,$20,$B5,$B3
   .DB   $20,$20,$B5,$B4
   .DB   $20,$20,$B5,$B5
   .DB   $20,$20,$B5,$B6
   .DB   $20,$20,$B5,$B7
   .DB   $20,$20,$B5,$B8
   .DB   $20,$20,$B5,$B9

   .DB   $20,$20,$B6,$B0
   .DB   $20,$20,$B6,$B1
   .DB   $20,$20,$B6,$B2
   .DB   $20,$20,$B6,$B3
   .DB   $20,$20,$B6,$B4
   .DB   $20,$20,$B6,$B5
   .DB   $20,$20,$B6,$B6
   .DB   $20,$20,$B6,$B7
   .DB   $20,$20,$B6,$B8
   .DB   $20,$20,$B6,$B9

   .DB   $20,$20,$B7,$B0
   .DB   $20,$20,$B7,$B1
   .DB   $20,$20,$B7,$B2
   .DB   $20,$20,$B7,$B3
   .DB   $20,$20,$B7,$B4
   .DB   $20,$20,$B7,$B5
   .DB   $20,$20,$B7,$B6
   .DB   $20,$20,$B7,$B7
   .DB   $20,$20,$B7,$B8
   .DB   $20,$20,$B7,$B9

   .DB   $20,$20,$B8,$B0
   .DB   $20,$20,$B8,$B1
   .DB   $20,$20,$B8,$B2
   .DB   $20,$20,$B8,$B3
   .DB   $20,$20,$B8,$B4
   .DB   $20,$20,$B8,$B5
   .DB   $20,$20,$B8,$B6
   .DB   $20,$20,$B8,$B7
   .DB   $20,$20,$B8,$B8
   .DB   $20,$20,$B8,$B9

   .DB   $20,$20,$B9,$B0
   .DB   $20,$20,$B9,$B1
   .DB   $20,$20,$B9,$B2
   .DB   $20,$20,$B9,$B3
   .DB   $20,$20,$B9,$B4
   .DB   $20,$20,$B9,$B5
   .DB   $20,$20,$B9,$B6
   .DB   $20,$20,$B9,$B7
   .DB   $20,$20,$B9,$B8
   .DB   $20,$20,$B9,$B9







   .DB   $20,$B1,$B0,$B0
   .DB   $20,$B1,$B0,$B1
   .DB   $20,$B1,$B0,$B2
   .DB   $20,$B1,$B0,$B3
   .DB   $20,$B1,$B0,$B4
   .DB   $20,$B1,$B0,$B5
   .DB   $20,$B1,$B0,$B6
   .DB   $20,$B1,$B0,$B7
   .DB   $20,$B1,$B0,$B8
   .DB   $20,$B1,$B0,$B9

   .DB   $20,$B1,$B1,$B0
   .DB   $20,$B1,$B1,$B1
   .DB   $20,$B1,$B1,$B2
   .DB   $20,$B1,$B1,$B3
   .DB   $20,$B1,$B1,$B4
   .DB   $20,$B1,$B1,$B5
   .DB   $20,$B1,$B1,$B6
   .DB   $20,$B1,$B1,$B7
   .DB   $20,$B1,$B1,$B8
   .DB   $20,$B1,$B1,$B9

   .DB   $20,$B1,$B2,$B0
   .DB   $20,$B1,$B2,$B1
   .DB   $20,$B1,$B2,$B2
   .DB   $20,$B1,$B2,$B3
   .DB   $20,$B1,$B2,$B4
   .DB   $20,$B1,$B2,$B5
   .DB   $20,$B1,$B2,$B6
   .DB   $20,$B1,$B2,$B7
   .DB   $20,$B1,$B2,$B8
   .DB   $20,$B1,$B2,$B9

   .DB   $20,$B1,$B3,$B0
   .DB   $20,$B1,$B3,$B1
   .DB   $20,$B1,$B3,$B2
   .DB   $20,$B1,$B3,$B3
   .DB   $20,$B1,$B3,$B4
   .DB   $20,$B1,$B3,$B5
   .DB   $20,$B1,$B3,$B6
   .DB   $20,$B1,$B3,$B7
   .DB   $20,$B1,$B3,$B8
   .DB   $20,$B1,$B3,$B9

   .DB   $20,$B1,$B4,$B0
   .DB   $20,$B1,$B4,$B1
   .DB   $20,$B1,$B4,$B2
   .DB   $20,$B1,$B4,$B3
   .DB   $20,$B1,$B4,$B4
   .DB   $20,$B1,$B4,$B5
   .DB   $20,$B1,$B4,$B6
   .DB   $20,$B1,$B4,$B7
   .DB   $20,$B1,$B4,$B8
   .DB   $20,$B1,$B4,$B9

   .DB   $20,$B1,$B5,$B0
   .DB   $20,$B1,$B5,$B1
   .DB   $20,$B1,$B5,$B2
   .DB   $20,$B1,$B5,$B3
   .DB   $20,$B1,$B5,$B4
   .DB   $20,$B1,$B5,$B5
   .DB   $20,$B1,$B5,$B6
   .DB   $20,$B1,$B5,$B7
   .DB   $20,$B1,$B5,$B8
   .DB   $20,$B1,$B5,$B9

   .DB   $20,$B1,$B6,$B0
   .DB   $20,$B1,$B6,$B1
   .DB   $20,$B1,$B6,$B2
   .DB   $20,$B1,$B6,$B3
   .DB   $20,$B1,$B6,$B4
   .DB   $20,$B1,$B6,$B5
   .DB   $20,$B1,$B6,$B6
   .DB   $20,$B1,$B6,$B7
   .DB   $20,$B1,$B6,$B8
   .DB   $20,$B1,$B6,$B9

   .DB   $20,$B1,$B7,$B0
   .DB   $20,$B1,$B7,$B1
   .DB   $20,$B1,$B7,$B2
   .DB   $20,$B1,$B7,$B3
   .DB   $20,$B1,$B7,$B4
   .DB   $20,$B1,$B7,$B5
   .DB   $20,$B1,$B7,$B6
   .DB   $20,$B1,$B7,$B7
   .DB   $20,$B1,$B7,$B8
   .DB   $20,$B1,$B7,$B9

   .DB   $20,$B1,$B8,$B0
   .DB   $20,$B1,$B8,$B1
   .DB   $20,$B1,$B8,$B2
   .DB   $20,$B1,$B8,$B3
   .DB   $20,$B1,$B8,$B4
   .DB   $20,$B1,$B8,$B5
   .DB   $20,$B1,$B8,$B6
   .DB   $20,$B1,$B8,$B7
   .DB   $20,$B1,$B8,$B8
   .DB   $20,$B1,$B8,$B9

   .DB   $20,$B1,$B9,$B0
   .DB   $20,$B1,$B9,$B1
   .DB   $20,$B1,$B9,$B2
   .DB   $20,$B1,$B9,$B3
   .DB   $20,$B1,$B9,$B4
   .DB   $20,$B1,$B9,$B5
   .DB   $20,$B1,$B9,$B6
   .DB   $20,$B1,$B9,$B7
   .DB   $20,$B1,$B9,$B8
   .DB   $20,$B1,$B9,$B9




   .DB   $20,$B2,$B0,$B0
   .DB   $20,$B2,$B0,$B1
   .DB   $20,$B2,$B0,$B2
   .DB   $20,$B2,$B0,$B3
   .DB   $20,$B2,$B0,$B4
   .DB   $20,$B2,$B0,$B5
   .DB   $20,$B2,$B0,$B6
   .DB   $20,$B2,$B0,$B7
   .DB   $20,$B2,$B0,$B8
   .DB   $20,$B2,$B0,$B9


   .DB   $20,$B2,$B1,$B0
   .DB   $20,$B2,$B1,$B1
   .DB   $20,$B2,$B1,$B2
   .DB   $20,$B2,$B1,$B3
   .DB   $20,$B2,$B1,$B4
   .DB   $20,$B2,$B1,$B5
   .DB   $20,$B2,$B1,$B6
   .DB   $20,$B2,$B1,$B7
   .DB   $20,$B2,$B1,$B8
   .DB   $20,$B2,$B1,$B9

   .DB   $20,$B2,$B2,$B0
   .DB   $20,$B2,$B2,$B1
   .DB   $20,$B2,$B2,$B2
   .DB   $20,$B2,$B2,$B3
   .DB   $20,$B2,$B2,$B4
   .DB   $20,$B2,$B2,$B5
   .DB   $20,$B2,$B2,$B6
   .DB   $20,$B2,$B2,$B7
   .DB   $20,$B2,$B2,$B8
   .DB   $20,$B2,$B2,$B9

   .DB   $20,$B2,$B3,$B0
   .DB   $20,$B2,$B3,$B1
   .DB   $20,$B2,$B3,$B2
   .DB   $20,$B2,$B3,$B3
   .DB   $20,$B2,$B3,$B4
   .DB   $20,$B2,$B3,$B5
   .DB   $20,$B2,$B3,$B6
   .DB   $20,$B2,$B3,$B7
   .DB   $20,$B2,$B3,$B8
   .DB   $20,$B2,$B3,$B9

   .DB   $20,$B2,$B4,$B0
   .DB   $20,$B2,$B4,$B1
   .DB   $20,$B2,$B4,$B2
   .DB   $20,$B2,$B4,$B3
   .DB   $20,$B2,$B4,$B4
   .DB   $20,$B2,$B4,$B5
   .DB   $20,$B2,$B4,$B6
   .DB   $20,$B2,$B4,$B7
   .DB   $20,$B2,$B4,$B8
   .DB   $20,$B2,$B4,$B9

   .DB   $20,$B2,$B5,$B0
   .DB   $20,$B2,$B5,$B1
   .DB   $20,$B2,$B5,$B2
   .DB   $20,$B2,$B5,$B3
   .DB   $20,$B2,$B5,$B4
   .DB   $20,$B2,$B5,$B5
;   .DB   $20,$10,$10,$10      ;^^^
.EXIT

Re: Преобразование байта в три десятичные цифры

Вт июл 02, 2019 14:21:19

я вообще не могу представить ситуацию, когда требуется очень быстро преобразовать 1 байт.
а еще угробить 1 Кб программной памяти при этом...
к тому же, обычно приходится преобразовывать двухбайтовые числа.
а один байт - это такая большая редкость, что за нее бороться нет никакого смысла.

Re: Преобразование байта в три десятичные цифры

Ср июл 03, 2019 04:15:15

Малоубедительно. В теме более половины постов по быстрому преобразованию. У тебя просто не было таких задач. Удачи.

Re: Преобразование байта в три десятичные цифры

Ср июл 03, 2019 05:56:39

Обычно, если где-то нужно сделать много и быстро, я смотрю, а нельзя ли это много сделать заранее, обычно оказывается можно...
Те-же цифры: готовить следующий разряд не когда его уже зажигать пора, а как только завершились операции по зажиганию предыдущего, а как придет момент - просто взять готовый результат из буфера и применить.

Re: Преобразование байта в три десятичные цифры

Ср июл 03, 2019 07:35:16

Малоубедительно.

Малоубедительно. Обычно преобразование чисел требуется для вывода на дисплей. Ну, передать по интерфейсу.
Я не вижу ни одной задачи, ради которой нужно создавать огромную таблицу с целью сэкономить несколько тактов.

Re: Преобразование байта в три десятичные цифры

Ср июл 03, 2019 13:26:26

akl писал(а): У тебя просто не было таких задач.
а у тебя было?
да нет таких задач, где бы "лишние" 100, или даже 500, тактов создали цейтнот в вычислениях.
akl писал(а):В теме более половины постов по быстрому преобразованию.
это самая натуральная развлекуха, не имеющая практического смысла.

Re: Преобразование байта в три десятичные цифры

Вт июл 09, 2019 20:00:58

Собрался духом и реализовал и отладил код деления с остатком на 10 методом сдвигов и сложений для 16-ти и 24-битных величин.
Спойлер
Код:
;==============
.def    val1    =   r16
.def    val2    =   r17
.def    tmp1    =   r18
.def    tmp2    =   r19
.def    rem     =   r20
;==============
                ;   Процедура осуществляет деление 16-битной величины на 10 с остатком
                ;       методом сдвигов и сложений
                ;   Размер: 80 байт
                ;   Время: 40 тактов
                ;   Регистры: 5 штук
                ldi     val1,   0x5F    ;   Исходная величина
                ldi     val2,   0xEA
                mov     rem,    val1    ;   Подготовка к вычислению остатка
                ;   Расчёт целой части произведения делимого на величину 0.8 (10) =
                ;       = 0.1100 1100 1100 1100... (2)
                lsr     val2            ;   x 0.1 (2)           
                ror     val1
                mov     tmp1,   val1    ;   x 1.1 (2)
                mov     tmp2,   val2
                lsr     tmp2
                ror     tmp1
                add     val1,   tmp1
                adc     val2,   tmp2
                mov     tmp1,   val1    ;   x 1.0001 (2)
                swap    tmp1
                andi    tmp1,   0x0F
                mov     tmp2,   val2
                swap    tmp2
                eor     tmp1,   tmp2
                andi    tmp2,   0x0F
                eor     tmp1,   tmp2
                add     val1,   tmp1
                adc     val2,   tmp2
                ldi     tmp1,   0x01    ;   Инициализация вспомогательных 0 и 1
                ldi     tmp2,   0x00
                add     val1,   val2    ;   x 1.0000 0001 (2)
                adc     val2,   tmp2
                ;   Умножение сдвигами и сложением закончилось
                add     val1,   tmp1    ;   Коррекция рассчитанного произведения.
                adc     val2,   tmp2
                sbrc    val2,   7
                add     val1,   tmp1
                sbrc    val2,   7
                adc     val2,   tmp2
                andi    val1,   0xF8    ;   Искомое частное, умноженное на 8
                sub     rem,    val1    ;   Вычисление искомого остатка (вычитание)
                lsr     val2            ;       одновременно с искомым частным
                ror     val1            ;       (деление на 8)
                lsr     val2
                ror     val1
                sub     rem,    val1
                lsr     val2
                ror     val1
                ;   Конец процедуры
;==============
Спойлер
Код:
;==============
.def    val1    =   r16
.def    val2    =   r17
.def    val3    =   r18
.def    tmp1    =   r19
.def    tmp2    =   r20
.def    tmp3    =   r21
.def    rem     =   r22
;==============
                ;   Процедура осуществляет деление 24-битной величины на 10 с остатком
                ;       методом сдвигов и сложений
                ;   Размер: 122 байта
                ;   Время: 61 такт
                ;   Регистры: 7 штук
                ldi     val1,   0x7F    ;   Исходная величина
                ldi     val2,   0x96
                ldi     val3,   0x98
                mov     rem,    val1    ;   Подготовка к вычислению остатка
                ;   Расчёт целой части произведения делимого на величину 0.8 (10) =
                ;       = 0.1100 1100 1100 1100 1100 1100... (2)
                lsr     val3            ;   x 0.1 (2)           
                ror     val2
                ror     val1       
                mov     tmp1,   val1    ;   x 1.1 (2)
                mov     tmp2,   val2
                mov     tmp3,   val3
                lsr     tmp3
                ror     tmp2
                ror     tmp1
                add     val1,   tmp1
                adc     val2,   tmp2
                adc     val3,   tmp3
                mov     tmp1,   val1    ;   x 1.0001 (2)
                swap    tmp1
                andi    tmp1,   0x0F
                mov     tmp2,   val2
                swap    tmp2
                eor     tmp1,   tmp2
                andi    tmp2,   0x0F
                eor     tmp1,   tmp2
                mov     tmp3,   val3
                swap    tmp3
                eor     tmp2,   tmp3
                andi    tmp3,   0x0F
                eor     tmp2,   tmp3
                add     val1,   tmp1
                adc     val2,   tmp2
                adc     val3,   tmp3
                ldi     tmp1,   0x01    ;   Инициализация вспомогательных 0 и 1
                ldi     tmp2,   0x00
                add     val1,   val2    ;   x 1.0000 0001 (2)
                adc     val2,   val3
                adc     val3,   tmp2
                add     val1,   val3    ;   x 1.0000 0000 0000 0001 (2)
                adc     val2,   tmp2
                adc     val3,   tmp2
                ;   Умножение сдвигами и сложением закончилось
                add     val1,   tmp1    ;   Коррекция рассчитанного произведения.
                adc     val2,   tmp2
                adc     val3,   tmp2
                sbrc    val3,   7
                add     val1,   tmp1
                sbrc    val3,   7
                adc     val2,   tmp2
                sbrc    val3,   7
                adc     val3,   tmp2
                andi    val1,   0xF8    ;   Искомое частное, умноженное на 8
                sub     rem,    val1    ;   Вычисление искомого остатка (вычитание)
                lsr     val3            ;       одновременно с искомым частным
                ror     val2            ;       (деление на 8)
                ror     val1
                lsr     val3
                ror     val2
                ror     val1
                sub     rem,    val1
                lsr     val3
                ror     val2
                ror     val1
                ;   Конец процедуры
;==============

Довольно таки объёмный код получился.

Добавлено after 5 minutes 39 seconds:
B@R5uk писал(а):Так что к процедуре, которая вызывается раз в 20-40 мс, нет смысла предъявлять жёсткие требования по быстродействию.
а зачем так часто?
я вывожу на экран 3 раза в секунду, вместе с обработкой кнопок или энкодера, чтобы сразу видеть результат действия кнопок и энкодера. чаще выводить вообще нет никакого смысла.

Я фанат динамической индикации на семисегментниках, так как этот подход требует значительно меньше соединений и экономит буферные детали. А при динамической индикации "Бегущий огонёк" должен проскакивать по всем индикаторам как можно быстрее, чтобы создать иллюзию равномерного свечения. 25-50 раз в секунду — это в самый раз.

Re: Преобразование байта в три десятичные цифры

Вт июл 09, 2019 20:14:27

25- очень мало, 50 - только для неподвижного экрана, когда мне понадобились часы в машину, частоты ниже 500гц (на весь дисплей) были отметены сразу, иначе даже при небольшой тряске видно только набор сегментов...

Re: Преобразование байта в три десятичные цифры

Вт июл 09, 2019 20:47:19

Только сканирование матрицы вообще никак не связано с подготовкой данных для индикаторов! Или вы для каждого индикатора на лету вычисляет сегменты?! Это же кошмар не рождённого!

Re: Преобразование байта в три десятичные цифры

Вт июл 09, 2019 21:52:27

25- очень мало, 50 - только для неподвижного экрана, когда мне понадобились часы в машину, частоты ниже 500гц (на весь дисплей) были отметены сразу, иначе даже при небольшой тряске видно только набор сегментов...

Динамическую индикацию делал для частотомера, для счётчика витков и просто для экспериментального цифрового индикатора на АЛС318. Всё это стационарные устройства, так что небольшой частоты хватало. Возьму ваш опыт на заметку, если вдруг какие мобильные индикаторы буду делать. Спасибо.

ARV, у частотомера цикл измерения около секунды, на 16 МГц это как раз 24 значащих бит частоты. Так что раз в секунду и рассчитывал. Хотя можно придумать какой-нибудь скоростной режим с пониженной точностью и повышенной скоростью индикации. Чисто для разнообразия.

Re: Преобразование байта в три десятичные цифры

Ср июл 10, 2019 10:27:09

...Приводимый ниже рекордно быстрый алгоритм годится только для архитектуры MSP430X. В ней имеется таймер реального времени RTC_B, в состав которого входит регистр BIN2BCD...
Моё любимое семейство. Ниже приведен классический код преобразования в BCD с использованием команды сложения с десятичной коррекцией. Вы наверняка его знаете, но мало ли кому пригодится для этого семейства без встроенного регистра BIN2BCD. Он не такой шустрый, зато работает в диапазоне 0...65535. Очень легко наращивается для преобразования больших чисел. Жаль что AVR не имеет аналогичной команды.

Спойлер
Код:
BIN_BCD:
;R9-BIN   R13,R14-BCD формат старший-младший
    MOV #16,R15
    CLR R13
    CLR R14
BIN_BCD1:
    RLA R9
    DADD    R14,R14
    DADD    R13,R13

    DEC R15
    JNZ BIN_BCD1

;конец преобразования 100 циклов

Re: Преобразование байта в три десятичные цифры

Ср июл 10, 2019 10:45:28

B@R5uk писал(а):Так что раз в секунду и рассчитывал.
и для этого вам потребовалось достигать минимума тактов на преобразование?! Даже самый тупейший метод (кажется больше 700 тактов - поправьте, если ошибся) при тактовой частоте "всего" в 1 МГц за 1 секунду позволит преобразовать в символы 1428 байтов! :)

как было сказано, данная тема имеет чисто спортивный смысл, никакой практической пользы она не содержит.

Re: Преобразование байта в три десятичные цифры

Ср июл 10, 2019 11:28:20

2 AVR:
...просто спортивный и академический интерес...


Добавлено after 27 minutes 48 seconds:
Между тем, я тут подумал и понял: поскольку вычитание единицы из трёхбайтной величины довольно накладная операция на 8-битном МК, то в процедуре деления на 10 сдвигами и сложением этой 24-битной величины лучше коррекцию делать как было предложение в оригинальной статье: вычитанием в конце из остатка 10, если он больше 10, и увеличением частного на 1. Экономия в 3 такта:
Спойлер
Код:
;==============
.def    val1    =   r16
.def    val2    =   r17
.def    val3    =   r18
.def    tmp1    =   r19
.def    tmp2    =   r20
.def    tmp3    =   r21
.def    rem     =   r22
;==============
                ;   Процедура осуществляет деление 24-битной величины на 10 с остатком
                ;       методом сдвигов и сложений
                ;   Размер: 120 байт
                ;   Время: 58 тактов
                ;   Регистры: 7 штук
                ldi     val1,   0x75    ;   Исходная величина
                ldi     val2,   0x96
                ldi     val3,   0x98
                mov     rem,    val1    ;   Подготовка к вычислению остатка
                ;   Расчёт целой части произведения делимого на величину 0.8 (10) =
                ;       = 0.1100 1100 1100 1100 1100 1100... (2)
                lsr     val3            ;   x 0.1 (2)           
                ror     val2
                ror     val1       
                mov     tmp1,   val1    ;   x 1.1 (2)
                mov     tmp2,   val2
                mov     tmp3,   val3
                lsr     tmp3
                ror     tmp2
                ror     tmp1
                add     val1,   tmp1
                adc     val2,   tmp2
                adc     val3,   tmp3
                mov     tmp1,   val1    ;   x 1.0001 (2)
                swap    tmp1
                andi    tmp1,   0x0F
                mov     tmp2,   val2
                swap    tmp2
                eor     tmp1,   tmp2
                andi    tmp2,   0x0F
                eor     tmp1,   tmp2
                mov     tmp3,   val3
                swap    tmp3
                eor     tmp2,   tmp3
                andi    tmp3,   0x0F
                eor     tmp2,   tmp3
                add     val1,   tmp1
                adc     val2,   tmp2
                adc     val3,   tmp3
                ldi     tmp1,   0x01    ;   Инициализация вспомогательных 0 и 1
                ldi     tmp2,   0x00
                add     val1,   val2    ;   x 1.0000 0001 (2)
                adc     val2,   val3
                adc     val3,   tmp2
                add     val1,   val3    ;   x 1.0000 0000 0000 0001 (2)
                adc     val2,   tmp2
                adc     val3,   tmp2
                ;   Умножение сдвигами и сложением закончилось
                andi    val1,   0xF8    ;   Искомое частное, умноженное на 8
                sub     rem,    val1    ;   Вычисление искомого остатка (вычитание)
                lsr     val3            ;       одновременно с искомым частным
                ror     val2            ;       (деление на 8)
                ror     val1
                lsr     val3
                ror     val2
                ror     val1
                sub     rem,    val1
                lsr     val3
                ror     val2
                ror     val1
                ;   Коррекция результатов расчёта
                subi    rem,    0x0A    ;   Если остаток больше или равен 10, то
                brcc    PC+4
                subi    rem,    0xF6
                nop
                rjmp    PC+4
                add     val1,   tmp1    ;       уменьшить остаток на 10 и
                adc     val2,   tmp2    ;       увеличить частное на 1
                adc     val3,   tmp2
                ;   Конец процедуры
;==============
Ответить