Перейти к содержанию
    

веерная перетасовка бит в переменной Cortex M0

Все по той же матрично-светодидной теме ->
Есть 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 с битовыми операциями не густо
и битбандинга нет :wacko:
Изменено пользователем sherr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тактов на все про все не больше 60-70 ...

В лоб занимает > 200, табличный вариант оставил на крайний случай.

Может есть какой-то хитрый метод ?

А почему такое неприятие табличного метода??? Просто быстро и универсально.

Я плохо знаю систему команд M0, но думаю займёт тактов 20 примерно. И по памяти можно уложиться в 4 кБ флеша (хотя, если есть МНОГО памяти, можно за счёт неё ещё неск. тактов выиграть наверное).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут трюки с битами:Swapping individual bits with XOR . Может быть, поможет. Если время будет, попробую применить такой метод к вашей задаче.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Автору:

Вот тут чел страдает похожим: http://electronix.ru/forum/index.php?showt...p;#entry1407219

Может поможет?

 

PS: Только что в голову пришёл самый быстрый метод - в зависимости от функционирования GPIO в Вашем МК, этот метод вообще может занимать всего пару тактов :rolleyes:

Выделяете 2-а 32-битных порта GPIO. Соединяете вых. линии первого порта с вх. линиями второго в соответствии с таблицей перестановки бит, выводите слово в первый порт, считываете со второго. На ядре M3 этот алгоритм может занимать всего два такта, если GPIO сидит на быстрой шине.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

PS: Только что в голову пришёл самый быстрый метод - в зависимости от функционирования GPIO в Вашем МК, этот метод вообще может занимать всего пару тактов :rolleyes:

Выделяете 2-а 32-битных порта GPIO. Соединяете вых. линии первого порта с вх. линиями второго в соответствии с таблицей перестановки бит, выводите слово в первый порт, считываете со второго. На ядре M3 этот алгоритм может занимать всего два такта, если GPIO сидит на быстрой шине.

Гениально ! Да только ног свободных столько нету...

А почему такое неприятие табличного метода??? Просто быстро и универсально.

Я плохо знаю систему команд M0, но думаю займёт тактов 20 примерно. И по памяти можно уложиться в 4 кБ флеша (хотя, если есть МНОГО памяти, можно за счёт неё ещё неск. тактов выиграть наверное).

Там вообще-то минимум 32*6 32-битных слов в таблице - это и в ОЗУ влезет если надо,,,,

 

 

 

Изменено пользователем sherr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там вообще-то минимум 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. В результате получаем то, что требовалось.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На ядре M3 этот алгоритм может занимать всего два такта, если GPIO сидит на быстрой шине.

Можно ссылочку на камень, который умеет записывать в периферию (я так понимаю, это непосредственная адресация?) в 1 такт?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал.

На картинке:

1 строка - входные биты

2 строка - номера для bit_table_item

3 строка - выходные биты

4 строка - номера для table

.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

 

Листинг

	.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: подрихтовал

post-27702-1456515275_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал.

Спасибо ,Пока не могу оценить - в ассемблере слаб (и вот повод подразобраться),

Тоже сделал на С, ну как умею


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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В принципе задача сводится к пяти преобразованиям типа :

ABCDxxxxxxx,,, в A00000B00000C00000D00000... где A-D это биты

Это преобразование можно сделать так:

y = ((x & 0xF) * 0x8421) & 0x41041;

Если умножение за один такт, то может получиться очень интересно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А подскажите, как обратное преобразование сделать,

в частности у меня A0000B00000C0000D0000E00000F0000 -> .....000000ABCDEF00 ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А подскажите, как обратное преобразование сделать,

в частности у меня A0000B00000C0000D0000E00000F0000 -> .....000000ABCDEF00 ?

Побитово собирать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Побитово собирать.

чтобы собирать быстрее, надо использовать группирование:

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...