пяти битная система перевод в восьми битную и наоборот

Vладимир
Offline
Зарегистрирован: 27.01.2015

Всем привет .

задача : обработать данные от некоего устройства которое шлет пакет из 25 байт (8*25=200 бит) но в этих 200 битах  40 слов по 5 бит на каждое , нужно извлеч инфу и поместить в байтовый массив размерностью 40.

как это зделать через цикл и побитное сравнение я знаю , но ето слишком медленно работает , может есть более простое и правильное решение

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Достаточно абстрактная задача, неизвестно в каком виде и с какого интерфейса получаем данные, есть вариант на лету преобразовывать, а не собирать данные, а потом их преобразовывать.

А если рассматривать задачу как массив из 25 байтов преобразовать в другой массив в 40 байтов, то это совсем другая задача. Плюс "слишком медленно" тоже относительно. Можно выложить скетч, посмотрим, может что то не оптимально написано? Фраза "побитное сравнение" навевает на что то странное. При преобразовании нет нужды сравнивать, навскидку, здесь нужно только считывать, сдвигать, очищать по маске и складывать, строчек 7-10.

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

Угу, совершенно верно. << >> рулят 

Vладимир
Offline
Зарегистрирован: 27.01.2015

тестовый скетч выглядит так и на 16мегагерцовой уне отрабатывает конвертирование за 1960 микросек


unsigned long starttime;

byte in[25];
byte out[40];
//---------------------------------------------------
void convert_5_to_8()
{
  for (byte n=0;n<sizeof(in)*8;n++)  // 200 бит
    {
       byte in_byte=n / 5;   // для наглядности в отдельных переменных
       byte in_bit=n % 5;
       byte out_byte=n / 8;
       byte out_bit=n % 8;
       bitWrite(out[in_byte],in_bit,bitRead(in[out_byte],out_bit));
    }
}

//---------------------------------------------------

void convert_8_to_5()
{
  for (byte n=0;n<sizeof(in)*8;n++)  // 200 бит
    {
       byte in_byte=n / 8;  // для наглядности в отдельных переменных
       byte in_bit=n % 8;
       byte out_byte=n / 5;
       byte out_bit=n % 5;
       bitWrite(in[in_byte],in_bit,bitRead(out[out_byte], out_bit));
    }
}

//-------------------------------------------------------



void showresult(unsigned long tt)
{
   Serial.begin(9600);
  for (byte i=0;i<sizeof(out);i++)
   {
      Serial.print("OUT[ "+String(i)+" ]="+out[i]+" Bin ");   
      Serial.println(out[i],BIN);
   }
Serial.println("----------------------------------------");
Serial.println("in work time: "+String(tt)+" micros");
}
//------------------------------------------------------------


void setup() 
{ 
    for (byte n=0;n < sizeof(in);n++) in[n]=0;
    for (byte n=0;n < sizeof(out);n++) out[n]=n;
  convert_8_to_5();
    for (byte n=0;n < sizeof(out);n++)out[n]=0;

  starttime=micros();
  convert_5_to_8();
  showresult(micros()-starttime);
}
//---------------------------------------------------------------------
void loop()
{

}

 

Vладимир
Offline
Зарегистрирован: 27.01.2015

с удовольствием приму в дар код который отработает в два раза быстрее 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Vладимир пишет:

с удовольствием приму в дар код который отработает в два раза быстрее 

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

и эт, даром, за амбаром!

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ну я так и подозревал. У Вас 200 циклов, когда можно обойтись примерно 25-ю. Маски, сдвиги, логические операции. Считали первый байт. 5 бит из него сохранили, 3 бита оставили в накопителе. Считали второй байт, из него взяли 2 бита и с 3 битами из накопителя получили 5 бит, сохранили. Из оставшихся 6 бит 5 сохранили, 1 бит в накопитель. И т.д. это один из простых алгоритмов, хотя у Вас ещё проще, потому и медленней. Хотя и его можно оптимизировать, кстати. И да, не принимайте в дар, получите дар самостоятельно, алгоритм я Вам подсказал.

UPD: ещё можно сделать по Вашему принципу, но за 40 циклов, каждый раз собирая биты из входного массива. Что оптимальней, надо пробовать.

UPD2: Результат 52 микросекунды - это результат по третьему алгоритму, в котором всего 5 циклов.

 
Vладимир
Offline
Зарегистрирован: 27.01.2015

to puhlyaviy

Serial.begin(9600); выполняется один раз , так как не находится в теле цикла

maksim
Offline
Зарегистрирован: 12.02.2012
void convert_5_to_8()
{
  for(byte i = 0, o = 0; i < 25; i+=5)
  {
    out[o++] = in[i]&0b11111;
    out[o++] = (in[i]>>5) | (in[i+1]<<3)&0b11111;
    out[o++] = (in[i+1]>>2)&0b11111;
    out[o++] = (in[i+1]>>7) | (in[i+2]<<1)&0b11111;
    out[o++] = (in[i+2]>>4) | (in[i+3]<<4)&0b11111;
    out[o++] = (in[i+3]>>1)&0b11111;
    out[o++] = (in[i+3]>>6) | (in[i+4]<<2)&0b11111;
    out[o++] = in[i+4]>>3;
  }
}
----------------------------------------
in work time: 72 micros

И научитесь отделять пробелами "слова" и "предложения" и не ставить пробелы там где они не нужны.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

У меня получилось 52 мкс видимо за счёт оптимизатор, плюс я использовал переменные и не читал из массива по несколько раз.
Запускал на Леонардо.
Да, АрдуиноИде 1.6.4 это тоже может быть важно.

Vладимир
Offline
Зарегистрирован: 27.01.2015

ради интереса прогнал свой код и код от maksim на DUE  результат  126 / 6