Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Перестановка бит в байте
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
bbill
Появилась необходимость (из-за разводки) перевернуть байт:
было 0b76543210
стало 0b01234567

Можно тупо bld/bst, но хотелось бы покороче. Кто сталкивался с подобной задачей.

P.S. В поиске нашел только обсуждение о перестановке двух бит.
=GM=
1) Если есть два свободных порта, переставить провода, как надо: выдал байт, считал перекодированный байт.

2) Если есть свободная память: перекодировочная таблица на 256 байт.
Maik-vs
Цитата(bbill @ Nov 6 2008, 14:28) *
Появилась необходимость (из-за разводки) перевернуть байт:
было 0b76543210
стало 0b01234567

Можно тупо bld/bst, но хотелось бы покороче. Кто сталкивался с подобной задачей.

P.S. В поиске нашел только обсуждение о перестановке двух бит.

Код
; 13 words / 13 cycles
; tmp= abcdefgh
    mov     tmp2,tmp; tmp2= abcdefgh
    andi     tmp2,0b01010101; tmp2= 0b0d0f0h
    andi     tmp, 0b10101010; tmp=  a0c0e0g0
    bst     tmp2,0; T=h
    lsr     tmp2 ; tmp2= 00b0d0f0
    bld     tmp2,7; tmp2= h0b0d0f0
    lsl     tmp ; tmp=  0c0e0g00 C=a
    adc     tmp, tmp2; tmp=  hcbedgfa
    mov     tmp2,tmp; tmp2= hcbedgfa
    andi     tmp2,0b01100110; tmp2= 0cb00gf0
    swap    tmp2 ; tmp2= 0gf00cb0
    andi     tmp, 0b10011001; tmp=  h00ed00a
    add     tmp, tmp2; tmp=  hgfedcba


так длинно? тогда в сад в порт
Сергей С.
Цитата(bbill @ Nov 6 2008, 16:28) *
Появилась необходимость (из-за разводки) перевернуть байт:
было 0b76543210
стало 0b01234567

Можно тупо bld/bst, но хотелось бы покороче. Кто сталкивался с подобной задачей.

P.S. В поиске нашел только обсуждение о перестановке двух бит.


Я когда такое делал, особо не задумывался, про bld/bst не знал, да и задачи экономии ресурсов не стояло. Поэтому получилась такая программа на C. (листинг после компиляции в WinAVR)

Код
static const uint8_t REVERT_NIBBLE[] =
{
    0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
    0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
};

uint8_t
Revert_Byte(uint8_t Data)
{
4ea:    98 2f           mov    r25, r24
4ec:    92 95           swap    r25
4ee:    9f 70           andi    r25, 0x0F; 15
4f0:    ed e4           ldi    r30, 0x4D; 77
4f2:    f1 e0           ldi    r31, 0x01; 1
4f4:    df 01           movw    r26, r30
4f6:    a9 0f           add    r26, r25
4f8:    b1 1d           adc    r27, r1
4fa:    8f 70           andi    r24, 0x0F; 15
4fc:    e8 0f           add    r30, r24
4fe:    f1 1d           adc    r31, r1
500:    80 81           ld    r24, Z
502:    82 95           swap    r24
504:    80 7f           andi    r24, 0xF0; 240
506:    9c 91           ld    r25, X
508:    89 2b           or    r24, r25
    return((REVERT_NIBBLE[Data >> 4]) | ((REVERT_NIBBLE[Data & 0x0F] << 4)));
}
50a:    99 27           eor    r25, r25
50c:    08 95           ret


IMHO на асме с bld/bst будет и короче и быстрее smile.gif
Vlad219i
Цитата(bbill @ Nov 6 2008, 15:28) *
Можно тупо bld/bst, но хотелось бы покороче. Кто сталкивался с подобной задачей.


Код
            ldi    cntreg,8
l1:        rol    tmp
            ror    tmp2
            dec    cntreg
            brne    l1


Покороче, но оч медленно. На выходе в tmp2 имеем перевертыш. Ну и регистры почем зря используем. :-)
МП41
Эх, не хватает однако подобной аппаратной команды. Можно сделать, чтобы побыстрее работало, но больше кода займёт.
Восемь раз вподряд фрагмент:
rol reg1
ror reg2
CDT
Цитата(bbill @ Nov 6 2008, 14:28) *
Появилась необходимость (из-за разводки) перевернуть байт:
было 0b76543210
стало 0b01234567

А если подумать и посчитать?
Код
;==============================================
;РАЗВОРОТ БАЙТА  7-0 в 0-7
;stable - время выполнения не зависит от данных

;---------------------------------------------------------------
; 16 words 18 clk stable (минус rjmp или ret)

M31:    bst    rTmp,0
    bld    rTmpH,7

    bst    rTmp,1
    bld    rTmpH,6

    bst    rTmp,2
    bld    rTmpH,5

    bst    rTmp,3
    bld    rTmpH,4

    bst    rTmp,4
    bld    rTmpH,3

    bst    rTmp,5
    bld    rTmpH,2

    bst    rTmp,6
    bld    rTmpH,1

    bst    rTmp,7
    bld    rTmpH,0
        rjmp M31


;-------------------------------------------------------------
; 5 words 42 clk stable (минус rjmp или ret)
M21:       ldi    rCnt,8
l1:        rol    rTmp
            ror    rTmpH
            dec    rCnt
            brne    l1
      rjmp    M21


;--------------------------------------------------------------
; 4 word's 32 clk stable
    ldi    rTmpH,1
M1:    lsr    rTmp
    rol    rTmpH
    brcc    M1


Выбирайте, что дороже: код, время и стабильность времени выполнения или время копирования одинаковых строк кода в редакторе.
AVR Studio легко позволяет почти все проверить и измерить, если не лениться.smile.gif
_Pasha
Код
rol tmp1
ror tmp2
;........rept 8 раз

А в чем проблема-то? Самый оптимальный вариант ведь...
А для чего это все? Константами низзя обойтись ?
bbill
Спасибо Maik-vs. И короче, и главное быстрее. А еще короче можешь biggrin.gif

Всем остальным спасибо за участие.

P.S. Что bld/bst, что ror/rol, та же пара регистров и те же 16 тактов. Циклы не считаем.
Мне в данном случае важнее скорость.
Aleksandr Baranov
Bit Order
Maik-vs
Цитата(bbill @ Nov 6 2008, 17:46) *
Спасибо Maik-vs. И короче, и главное быстрее. А еще короче можешь biggrin.gif


Да не за что, это даже не моё. Где-то пробегало в конфе, дай, думаю, положу в заначку - пригодится. Вот, пригодилось smile.gif
zombi
И всетаки мне кажется если скорость важнее то лучший вариант это таблица заранее перевернутых байтов и LPM
ARV
вот на телесистемах была пару раз ветка по этой теме (поиск рулит) - там просто перлы были! 11 тактов, кажется или даже меньше! у меня только 14...
singlskv
Цитата(ARV @ Nov 7 2008, 18:45) *
вот на телесистемах была пару раз ветка по этой теме (поиск рулит) - там просто перлы были! 11 тактов, кажется или даже меньше!

НЕ ВЕРЮ!
Покажите <13 на AVR...

на PIC можно за 12
ARV
Цитата(singlskv @ Nov 8 2008, 00:39) *
НЕ ВЕРЮ!
Покажите <13 на AVR...

на PIC можно за 12
да я не утверждаю - это скорее эмоции от впечатления - были какие-то просто поразившие меня виртуозности! поиском можно найти в архиве телесистем - за последние месяца 4 не один раз всплывали темы...
Qwertty
Цитата(singlskv @ Nov 8 2008, 00:39) *
на PIC можно за 12

Под "PIC" подразумевается 16-ая или 18-ая серии? Тогда интересно было бы взглянуть на реверс из трех инструкций... А для АВР можно и меньше 10 тактов если использовать таблицу.
_Pasha
Цитата(Qwertty @ Nov 8 2008, 08:27) *
А для АВР можно и меньше 10 тактов если использовать таблицу.

Угу.
Код
  movw SaveZ,zL
  ldi      zh,high(bit_rev_table << 1)
; и занимайтесь скока угодно
mov    zL,r0
lpm
;....................
movw zL,SaveZ
ae_
Цитата(singlskv @ Nov 8 2008, 06:39) *
НЕ ВЕРЮ!
Покажите <13 на AVR...

на PIC можно за 12

12 тактов
Код
Reverse_1:; реверс бит в байте (R4 - вход/выход)

; обмен средних бит в тетрадах
mov R17,R4
andi R17,0b10011001
sub R4,R17
swap R4
or R4,R17
; выделение четных/нечетных бит
mov R17,R4
andi R17,0b10101010
sub R4,R17
; обмен четных/нечетных бит
out SREG,R4
ror R4
lsl R17
adc R4,R17

Порядок преобразования:
a b c d e f g h C
a f g d e b c h 0
a - g - e - c - 0
- f - d - b - h 0
h - f - d - b - -
- g - e - c - - a
h g f e d c b a 0

Единственный тонкий момент: обнуление I (запрет прерываний)
С разбегу обойти его мне не удалось без добавления 13-го такта.

©argus98 - все права защищены :))
singlskv
Цитата(ae_ @ Nov 8 2008, 13:43) *
12 тактов
Код
Reverse_1:; реверс бит в байте (R4 - вход/выход)

; обмен средних бит в тетрадах
mov R17,R4
andi R17,0b10011001
sub R4,R17
swap R4
or R4,R17
; выделение четных/нечетных бит
mov R17,R4
andi R17,0b10101010
sub R4,R17
; обмен четных/нечетных бит
out SREG,R4
ror R4
lsl R17
adc R4,R17

Порядок преобразования:
a b c d e f g h C
a f g d e b c h 0
a - g - e - c - 0
- f - d - b - h 0
h - f - d - b - -
- g - e - c - - a
h g f e d c b a 0

Единственный тонкий момент: обнуление I (запрет прерываний)
С разбегу обойти его мне не удалось без добавления 13-го такта.

Ну это не до конца честный вариант,
Код
out SREG,R4
ror R4

нужно менять на
Код
    bst     R4,0
    lsr      R4
    bld     R4,7
а это уже 13 тактов...



Кстати говоря, тк тема снова всплыла, есть небольшая модификация 13тактового алгоритма
которая позволяет отказаться от использования бита T в SREG:
Код
; 13 words / 13 cycles
;                            ;tmp=  abcdefgh
    mov     tmp2, tmp        ;tmp2= abcdefgh
    asr     tmp              ;tmp=  aabcdefg C=h
    ror     tmp2             ;tmp2= habcdefg C=h
    rol     tmp              ;tmp=  abcdefgh C=a
    rol     tmp              ;tmp=  bcdefgha
    andi    tmp2, 0b10101010 ;tmp2= h0b0d0f0
    andi    tmp,  0b01010101 ;tmp=  0c0e0g0a
    add     tmp,  tmp2       ;tmp=  hcbedgfa
    mov     tmp2, tmp        ;tmp2= hcbedgfa
    andi    tmp2, 0b01100110 ;tmp2= 0cb00gf0
    swap    tmp2             ;tmp2= 0gf00cb0
    andi    tmp,  0b10011001 ;tmp=  h00ed00a
    add     tmp,  tmp2       ;tmp=  hgfedcba

но увы все равно 13... sad.gif


Цитата(Qwertty @ Nov 8 2008, 08:27) *
Под "PIC" подразумевается 16-ая или 18-ая серии? Тогда интересно было бы взглянуть на реверс из трех инструкций...

Увы, для PIC сейчас найти не могу, а писать заново не буду, Пики я только "со словарем", потаму
как редко...
Насколько я помню, пойдет даже на 10/12 серии...,
экономия 1 такта там из-за аккамуляторной модели, типа можно сделать сдвиг и получить
в результате 2 числа одно сдвинутое а второе исходное... как то так...
Qwertty
Цитата(singlskv @ Nov 8 2008, 23:22) *
Увы, для PIC сейчас найти не могу, а писать заново не буду, Пики я только "со словарем", потаму
как редко...
Насколько я помню, пойдет даже на 10/12 серии...,
экономия 1 такта там из-за аккамуляторной модели, типа можно сделать сдвиг и получить
в результате 2 числа одно сдвинутое а второе исходное... как то так...

Идет даже на 10/12 серии!!! Напряжение нарастает smile.gif За 12 тактов 10/12/16/18 серии выполняют ТРИ коротких инструкции или 1,5 длинных. Как в это упаковать реверс 8 бит я не понимаю.
ae_
Цитата(Qwertty @ Nov 9 2008, 07:42) *
Идет даже на 10/12 серии!!! Напряжение нарастает :) За 12 тактов 10/12/16/18 серии выполняют ТРИ коротких инструкции или 1,5 длинных. Как в это упаковать реверс 8 бит я не понимаю.

Для PIC "такты" нужно заменить на "МЦ", для AVR тоже можно заменить, но т.к. для AVR они совпадают, то "такт" часто используется вместо "МЦ".
singlskv
Цитата(Qwertty @ Nov 9 2008, 01:42) *
Идет даже на 10/12 серии!!! Напряжение нарастает smile.gif За 12 тактов 10/12/16/18 серии выполняют ТРИ коротких инструкции или 1,5 длинных. Как в это упаковать реверс 8 бит я не понимаю.
Конечно я имел в виду "МЦ"... smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.