|
|
  |
веерная перетасовка бит в переменной Cortex M0 |
|
|
|
Feb 26 2016, 14:27
|
Местный
  
Группа: Участник
Сообщений: 257
Регистрация: 10-06-06
Из: Ставрополь
Пользователь №: 17 955

|
Все по той же матрично-светодидной теме -> Есть 32-битная переменная ,Надо ее преобразовать так (ниже номера бит) Было: 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,12,21,22,23,24,25,26 ,27,28,29,30,31 Стало: хх,хх, 00,06,11,16,22,27,01,07,12,17,23,28,02,08,13,18,24,29,03,09,14,19,25,30,04,10,15 ,20,26,31 Тактов на все про все не больше 60-70 ... В лоб занимает > 200, табличный вариант оставил на крайний случай. Может есть какой-то хитрый метод ? В принципе задача сводится к пяти преобразованиям типа : ABCDxxxxxxx,,, в A00000B00000C00000D00000... где A-D это биты, с последующим суммированием . ps увы, в системе команд STM32F0 с битовыми операциями не густо и битбандинга нет
Сообщение отредактировал sherr - Feb 26 2016, 14:34
|
|
|
|
|
Feb 26 2016, 15:44
|
Местный
  
Группа: Участник
Сообщений: 257
Регистрация: 10-06-06
Из: Ставрополь
Пользователь №: 17 955

|
Цитата(jcxz @ Feb 26 2016, 18:34)  PS: Только что в голову пришёл самый быстрый метод - в зависимости от функционирования GPIO в Вашем МК, этот метод вообще может занимать всего пару тактов Выделяете 2-а 32-битных порта GPIO. Соединяете вых. линии первого порта с вх. линиями второго в соответствии с таблицей перестановки бит, выводите слово в первый порт, считываете со второго. На ядре M3 этот алгоритм может занимать всего два такта, если GPIO сидит на быстрой шине. Гениально ! Да только ног свободных столько нету... Цитата(jcxz @ Feb 26 2016, 18:08)  А почему такое неприятие табличного метода??? Просто быстро и универсально. Я плохо знаю систему команд M0, но думаю займёт тактов 20 примерно. И по памяти можно уложиться в 4 кБ флеша (хотя, если есть МНОГО памяти, можно за счёт неё ещё неск. тактов выиграть наверное). Там вообще-то минимум 32*6 32-битных слов в таблице - это и в ОЗУ влезет если надо,,,,
Сообщение отредактировал sherr - Feb 26 2016, 16:00
|
|
|
|
|
Feb 26 2016, 18:01
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(sherr @ Feb 26 2016, 18:44)  Там вообще-то минимум 32*6 32-битных слов в таблице - это и в ОЗУ влезет если надо,,,, Это как считали? У меня получается 16 32-битных слов. Пример 16-битный легко переделать в 32 бита. Исходное число: A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, A4, B4, C4, D4. Результат: A1, A2, A3, A4, B1, B2, B3, B4, C1, C2, C3, C4, D1, D2, D3, D4. 0. Обнуляем результат. 1. Сдвигаем исходное число вправо на (16 - 4 * (1 + 0)) разрядов и делаем AND с 15. 2. Получаем A1 B1 C1 D1. 3. Используем как индекс в таблице и получаем из таблицы A1, 0, 0, 0, B1, 0, 0, 0, C1, 0, 0, 0, D1, 0, 0, 0. 4. Сдвигаем на 0 вправо и делаем OR с результатом. 5. Сдвигаем исходное число вправо на (16 - 4 * (1 + 1)) разрядов и делаем AND с 15. 6. Получаем A2 B2 C2 D2. 7. Используем как индекс в таблице и получаем из таблицы A2, 0, 0, 0, B2, 0, 0, 0, C2, 0, 0, 0, D2, 0, 0, 0. 8. Сдвигаем на 1 вправо и делаем OR с результатом. 9. Повторяем сдвиг на (16 - 4 * (1 + n)) исходного числа с последующим AND 15 и извлечением из таблицы. Данные из таблицы сдвигаем на n и делаем OR с результатом. Для n=2 и n=3. 10. В результате получаем то, что требовалось.
|
|
|
|
|
Feb 26 2016, 19:35
|
Знающий
   
Группа: Участник
Сообщений: 916
Регистрация: 3-10-08
Из: Москва
Пользователь №: 40 664

|
Цитата На ядре M3 этот алгоритм может занимать всего два такта, если GPIO сидит на быстрой шине. Можно ссылочку на камень, который умеет записывать в периферию (я так понимаю, это непосредственная адресация?) в 1 такт?
|
|
|
|
|
Feb 26 2016, 19:46
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Сделал. На картинке: 1 строка - входные биты 2 строка - номера для bit_table_item 3 строка - выходные биты 4 строка - номера для table CODE .macro bit_table_item shift_in shift_out lsrs r4, r0, # \shift_in ands r4, r3 ldr r4, [r2, r4] .if \shift_out lsrs r4, # \shift_out .endif orrs r1, r4 .endm
.global bit_table bit_table: push {r1-r4, lr} eors r1, r1 ldr r2, table ldr r3, =#31 bit_table_item 27 0 bit_table_item 21 1 bit_table_item 16 2 bit_table_item 11 3 bit_table_item 5 4 bit_table_item 0 5 mov r0, r1 pop {r1-r4, pc}
.macro table_item b4 b3 b2 b1 b0 .word (\b4 << 29) | (\b3 << 23) | (\b2 << 17) | (\b1 << 11) | (\b0 << 5) .endm .align 4 table: table_item 0 0 0 0 0 table_item 0 0 0 0 1 table_item 0 0 0 1 0 table_item 0 0 0 1 1 table_item 0 0 1 0 0 table_item 0 0 1 0 1 table_item 0 0 1 1 0 table_item 0 0 1 1 1 table_item 0 1 0 0 0 table_item 0 1 0 0 1 table_item 0 1 0 1 0 table_item 0 1 0 1 1 table_item 0 1 1 0 0 table_item 0 1 1 0 1 table_item 0 1 1 1 0 table_item 0 1 1 1 1 table_item 1 0 0 0 0 table_item 1 0 0 0 1 table_item 1 0 0 1 0 table_item 1 0 0 1 1 table_item 1 0 1 0 0 table_item 1 0 1 0 1 table_item 1 0 1 1 0 table_item 1 0 1 1 1 table_item 1 1 0 0 0 table_item 1 1 0 0 1 table_item 1 1 0 1 0 table_item 1 1 0 1 1 table_item 1 1 1 0 0 table_item 1 1 1 0 1 table_item 1 1 1 1 0 table_item 1 1 1 1 1
Листинг CODE .global bit_table bit_table: push {r1-r4, lr} 8003978: b51e push {r1, r2, r3, r4, lr} eors r1, r1 800397a: 4049 eors r1, r1 ldr r2, table 800397c: 4a10 ldr r2, [pc, #64] ; (80039c0 <table>) ldr r3, =#31 800397e: 4b32 ldr r3, [pc, #200] ; (8003a48 <table+0x88> = 0x1F) bit_table_item 27 0 8003980: 0ec4 lsrs r4, r0, #27 8003982: 401c ands r4, r3 8003984: 5914 ldr r4, [r2, r4] 8003986: 4321 orrs r1, r4 bit_table_item 21 1 8003988: 0d44 lsrs r4, r0, #21 800398a: 401c ands r4, r3 800398c: 5914 ldr r4, [r2, r4] 800398e: 0864 lsrs r4, r4, #1 8003990: 4321 orrs r1, r4 bit_table_item 16 2 8003992: 0c04 lsrs r4, r0, #16 8003994: 401c ands r4, r3 8003996: 5914 ldr r4, [r2, r4] 8003998: 08a4 lsrs r4, r4, #2 800399a: 4321 orrs r1, r4 bit_table_item 11 3 800399c: 0ac4 lsrs r4, r0, #11 800399e: 401c ands r4, r3 80039a0: 5914 ldr r4, [r2, r4] 80039a2: 08e4 lsrs r4, r4, #3 80039a4: 4321 orrs r1, r4 bit_table_item 5 4 80039a6: 0944 lsrs r4, r0, #5 80039a8: 401c ands r4, r3 80039aa: 5914 ldr r4, [r2, r4] 80039ac: 0924 lsrs r4, r4, #4 80039ae: 4321 orrs r1, r4 bit_table_item 0 5 80039b0: 0004 movs r4, r0 80039b2: 401c ands r4, r3 80039b4: 5914 ldr r4, [r2, r4] 80039b6: 0964 lsrs r4, r4, #5 80039b8: 4321 orrs r1, r4 mov r0, r1 80039ba: 4608 mov r0, r1 pop {r1-r4, pc} 80039bc: bd1e pop {r1, r2, r3, r4, pc} 80039be: 46c0 nop
080039c0 <table>: 80039c0: 00000000 .word 0x00000000 80039c4: 00000020 .word 0x00000020 80039c8: 00000800 .word 0x00000800 80039cc: 00000820 .word 0x00000820 80039d0: 00020000 .word 0x00020000 80039d4: 00020020 .word 0x00020020 80039d8: 00020800 .word 0x00020800 80039dc: 00020820 .word 0x00020820 80039e0: 00800000 .word 0x00800000 80039e4: 00800020 .word 0x00800020 80039e8: 00800800 .word 0x00800800 80039ec: 00800820 .word 0x00800820 80039f0: 00820000 .word 0x00820000 80039f4: 00820020 .word 0x00820020 80039f8: 00820800 .word 0x00820800 80039fc: 00820820 .word 0x00820820 8003a00: 20000000 .word 0x20000000 8003a04: 20000020 .word 0x20000020 8003a08: 20000800 .word 0x20000800 8003a0c: 20000820 .word 0x20000820 8003a10: 20020000 .word 0x20020000 8003a14: 20020020 .word 0x20020020 8003a18: 20020800 .word 0x20020800 8003a1c: 20020820 .word 0x20020820 8003a20: 20800000 .word 0x20800000 8003a24: 20800020 .word 0x20800020 8003a28: 20800800 .word 0x20800800 8003a2c: 20800820 .word 0x20800820 8003a30: 20820000 .word 0x20820000 8003a34: 20820020 .word 0x20820020 8003a38: 20820800 .word 0x20820800 8003a3c: 20820820 .word 0x20820820
8003a40: e000ed0c .word 0xe000ed0c ; левое 8003a44: 05fa0004 .word 0x05fa0004 ; левое 8003a48: 0000001f .word 0x0000001f
UDP: подрихтовал
Эскизы прикрепленных изображений
|
|
|
|
|
Feb 26 2016, 20:26
|
Местный
  
Группа: Участник
Сообщений: 257
Регистрация: 10-06-06
Из: Ставрополь
Пользователь №: 17 955

|
Цитата(adnega @ Feb 26 2016, 22:46)  Сделал. Спасибо ,Пока не могу оценить - в ассемблере слаб (и вот повод подразобраться), Тоже сделал на С, ну как умею CODE
uint32_t const bitveer [32]= {// 10987654321098765432109876543210 0b00000000000000000000000000000000, 0b00000000000000000000000000000100, 0b00000000000000000000000100000000, 0b00000000000000000000000100000100, 0b00000000000000000100000000000000, 0b00000000000000000100000000000100, 0b00000000000000000100000100000000, 0b00000000000000000100000100000100, 0b00000000000100000000000000000000, 0b00000000000100000000000000000100, 0b00000000000100000000000100000000, 0b00000000000100000000000100000100, 0b00000000000100000100000000000000, 0b00000000000100000100000000000100, 0b00000000000100000100000100000000, 0b00000000000100000100000100000100,//15 0b00000100000000000000000000000000, 0b00000100000000000000000000000100, 0b00000100000000000000000100000000, 0b00000100000000000000000100000100, 0b00000100000000000100000000000000, 0b00000100000000000100000000000100, 0b00000100000000000100000100000000, 0b00000100000000000100000100000100, 0b00000100000100000000000000000000, 0b00000100000100000000000000000100, 0b00000100000100000000000100000000, 0b00000100000100000000000100000100, 0b00000100000100000100000000000000, 0b00000100000100000100000000000100, 0b00000100000100000100000100000000, 0b00000100000100000100000100000100//31 }; /*****************************************************************/ uint32_t cms[1024];//matrix of leds 16*64 --> low 16 bit is pixel of line 0.1.2... ,high - line 16, 17. 18 ... in BGR16 format uint32_t lin[64]; // line buffer B4H.G4H.R4H.B4L........R0L.0.0 /*****************************************************************/
void fill_string (uint16_t num) //num is LED line number(0-15) {
uint32_t tm = 0, z = 0;// temp variables uint16_t adr=0,adr_st=0;//temp vars of adresses ->string 0-15;16-31,
adr = num*64; for(int i=0;i<64;i++) { tm = 0; z = cms[adr]; // cells (2*rgb) to temp var tm = bitveer[(z & 0x1F)]; //table conversion z>>=6 ; //Green0 is unneeded bit tm |= (bitveer[(z & 0x1F)]<<1); z>>=5 ; tm |= (bitveer[(z & 0x1F)]<<2); z>>=5 ; tm |= (bitveer[(z & 0x1F)]<<3); z>>=6 ; tm |= (bitveer[(z & 0x1F)]<<4); z>>=5 ; tm |= (bitveer[(z & 0x1F)]<<5); lin[adr_st] = tm ;
adr++; adr_st++;
}
}
, стало быстрее почти в 4 раза,
Сообщение отредактировал sherr - Feb 26 2016, 20:30
|
|
|
|
|
Feb 27 2016, 10:10
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(sherr @ Feb 26 2016, 17:27)  В принципе задача сводится к пяти преобразованиям типа : ABCDxxxxxxx,,, в A00000B00000C00000D00000... где A-D это биты Это преобразование можно сделать так: Код y = ((x & 0xF) * 0x8421) & 0x41041; Если умножение за один такт, то может получиться очень интересно.
|
|
|
|
|
Mar 4 2016, 08:30
|
Местный
  
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877

|
Цитата(adnega @ Mar 4 2016, 10:38)  Побитово собирать. чтобы собирать быстрее, надо использовать группирование: 1) A0000B0000C0000D0000E0000F0000 -> AB000BC000CD000DE000EF000F0000 2) AB000 BC000 CD000 DE000 EF000 F0000 -> AB000 00000 CD000 DE000 00000 F0000 2) AB000 00000 CD000 DE000 00000 F0000 -> ABDE0 00000 CDF00 DE000 00000 F0000 3) ABDE0 00000 CDF00 DE00 00000 F0000 ->
Сообщение отредактировал AlexRayne - Mar 4 2016, 08:42
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|