РЕШЕНО Как инвентировать байт?

Тема в разделе "Arduino & Shields", создана пользователем Suyano, 30 май 2020.

  1. Suyano

    Suyano Нерд

    Добрый день!

    Есть число (пример) 205.
    Код (C++):
    int color = 205;

    for(int i=0; i < 8; i++) {
       Serial.println(bitRead(color, i));
    }
    Результатом будет: 10110011

    Мне необходимо "развернуть" результат, чтобы было так: 11001101

    Вопрос:
    Как это можно сделать?

    Идеи:
    1) В bitRead начать счет битов справа налево. Вероятно, это неправильный путь с точки зрения времени выполнения.
    2) Использовать ~. Я поставил его для 205 и конечно это не привело к правильному результату.
     
  2. issaom

    issaom Гуру

    А так то чего не устраивает?
    Код (C++):
    for(int i=7; i > -1; i--) {
       Serial.println(bitRead(color, i));
    }
    оператор ~ просто переворачивает каждый бит в байте - если Вам нужно чтобы вместо 7-ого бита оказался 0 то он не подойдет.
     
    Suyano нравится это.
  3. Suyano

    Suyano Нерд

    @issaom

    Спасибо за ответ!
    Про i-- не знал. Так действительно подходит.

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

    Вопрос решен.
     
  4. b707

    b707 Гуру

    для управления ws2812 из-за требований ко времени обычно используют ассемблерный код. С использованием обычных операторв ардуино пока успешных вариантов не встречал. Если получится - потом поделитесь кодом
     
  5. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Это не инвертирование. Это "реверс бит". Команды ассемблера для такой операции не знаю. Хотя схемотехнически это не сложно было ввести в процессор.
     

    Вложения:

    Последнее редактирование: 31 май 2020
    Suyano нравится это.
  6. Suyano

    Suyano Нерд

    Прошу прощения за поздний ответ.
    Да, я видел пример на ассемблере, хотел попробовать без него.

    Код (C++):
    // Pin settings
    #define LED_PIN 10
    #define PORT PORTB
    #define PORT_PIN PORTB4

    void ledControl(int green, int red, int blue) {
      static unsigned long holdTimer;
      int colorBit = 0;
      int colorArray[3] = {green, red, blue};

      while((micros() - holdTimer) < 50L); // Wait 50us
      cli(); // Disable interrupts

      // Body
      // Select input color
      for(int colorCount=0; colorCount < 3; colorCount++) {
        // Set color in pixel
        for(int i=7; i > -1; i--) {
          colorBit = bitRead(colorArray[colorCount], i);
          // Select action (on or off)
          if(colorBit == 0) {
            // T0H
            bitSet(PORT, PORT_PIN);
            __builtin_avr_delay_cycles(3);
            // T0L
            bitClear(PORT, PORT_PIN);
            __builtin_avr_delay_cycles(6);
          } else {
            // T1H
            bitSet(PORT, PORT_PIN);
            __builtin_avr_delay_cycles(6);
            // T1L
            bitClear(PORT, PORT_PIN);
            __builtin_avr_delay_cycles(3);
          }
        }
      }

      sei(); // Enable interrupts
      holdTimer = micros();
    }

    void setup() {
      Serial.begin(115200);
      pinMode(LED_PIN, OUTPUT);
      digitalWrite(LED_PIN, LOW);
      ledControl(255, 0, 0);
      delay(1000);
      ledControl(0, 255, 0);
      delay(1000);
      ledControl(0, 0, 255);
      delay(1000);
      ledControl(100, 50, 25);
      delay(1000);
      ledControl(0, 0, 0);
    }

    void loop() {
      // Smooth kinding of light
      static bool lock = false;
      if(!lock) {
        for(int i=0; i<255; i++) {
          ledControl(0, 0, i);
          delay(15);
        }
        ledControl(0, 0, 0);
        lock = true;
      }
    }
    Работает для одного LED, в качестве RGB индикатора. Конечно есть задержка (50us), в моем случае это не критично. Цвета переключает нормально, но если менять яркость, как здесь, в loop() - вылетает несколько артефактов.