GyverLibs / GyverTransfer

Библиотека для передачи данных по интерфейсу GyverTransfer (GT). Передача для Arduino по одному проводу
MIT License
8 stars 2 forks source link

I added support for Attiny167 and a non-blocking way of writing a single byte in TRX. Can you check if it's right? #3

Open Rimbaldo opened 1 year ago

Rimbaldo commented 1 year ago

Hi!

I added some lines to add fastRead and fasWrite to attiny167. It seems to be working, but can you check it? I used the datasheet, but my knowledge in low level programming is limited...


  bool fastRead(const uint8_t pin) {
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
    if (pin < 8) return bitRead(PIND, pin);
    else if (pin < 14) return bitRead(PINB, pin - 8);
    else if (pin < 20) return bitRead(PINC, pin - 14);
#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
    return bitRead(PINB, pin);

    // ------------------------------Support for Attiny167-----------------------------------

#elif defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__)
    if (pin < 8) return bitRead(PINA, pin);
    else if (pin < 16) return bitRead(PINB, pin - 8);

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

#else
    return digitalRead(pin);
#endif
    return 0;
  }

  void fastWrite(const uint8_t pin, bool val) {
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
    if (pin < 8) bitWrite(PORTD, pin, val);
    else if (pin < 14) bitWrite(PORTB, (pin - 8), val);
    else if (pin < 20) bitWrite(PORTC, (pin - 14), val);
#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
    bitWrite(PORTB, pin, val);

 // -------------------------------------Support for Attiny167----------------------------

#elif defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__)
    if (pin < 8)  bitWrite(PORTA, pin, val);
    else if (pin < 16)  bitWrite(PORTB, (pin - 8), val);

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

#else
    digitalWrite(pin, val);
#endif
  }

And I created another write instance for sending a single byte in TRX only, non-blocking, based on state machine, called "bool writeTXRX_NB (unit8_t data)". I just got the write byte part and changed it to a non-blocking way. It returns 0 when the data was not sent, and 1 when it was sent.

Can you check the code to see if I did it right?? I added both codes (attiny167 support and this writeTXRX_NB) to my Gyvertransfer.h.

It compiles normally and works, but I don't think there's any speed advantage in the non-blocking way I did... maybe it needs to be improved? Can you check it? And correct me if I did something wrong?

 // SEND ONE BYTE BY TRX NON-BLOCKING WAY

  bool writeTXRX_NB(uint8_t data) {
    static uint8_t _write_state = 0;  // 0 = Idle. 1 = write requested, waiting to be ready (no sending). 2 = trigger write. 3 = write loop starts. 4  = write all 8 bits. 5 = writing is done
    static boolean dataReady = 0;
    static uint32_t nb_gtdelay = 0;  // timer counter for non blocking delays
    static bool flag_NB = 0;
    static uint8_t _data = 0;       // hold data value
    static uint8_t byte_count = 0;  // counter for the 8 bits of the byte

    switch (_write_state) {
      case 0:               // begin transmission sequence
        _data = data;       // byte to be sent
        dataReady = false;  // no data sent yet
        _write_state = 1;   // go to next state
        break;

      case 1:            //  write requested, waiting for receiving has ended
        if (parse == 1)  //if it's receiving, wait for the end of the reception
          break;
        else {               // if it´s not receiving
          transmitting = 1;  // flag to allow sending
          _write_state = 2;  // go to next state and disable interrupts

#ifdef GT_CLI
#ifdef AVR
          uint8_t sregSave = SREG;
#endif
          noInterrupts();
#endif
          break;
        }
        // break;

      case 2:  //  trigger write init:
        flag_NB = 0;
        setPin(0);              // set pin low - start pulse
        nb_gtdelay = micros();  // non blocking micros() delay start
        _write_state = 3;
        break;

      case 3:                                                             //  write loop start
        if (micros() - nb_gtdelay >= (GT_START(GT_SPEED) - GT_OFFSET)) {  // if start pulse length is ok
          nb_gtdelay = micros();                                          // non blocking micros() delay start again
          setPin(1);                                                      // set pin high - start pulse done
          _write_state = 4;                                               // go to next state
          break;
        }
        break;
      case 4:                  //  send bits 1 to 8
        if (byte_count < 8) {  // repeat this step until the eight bytes are sent
          if (_data & 1) {
            if (micros() - nb_gtdelay >= (GT_HIGH(GT_SPEED) - GT_OFFSET)) {  // wait for high pulse n to end
              nb_gtdelay = micros();                                         // non blocking micros() delay start again
              setPin(flag_NB);
              flag_NB = !flag_NB;
              _data >>= 1;
              byte_count++;
              break;
            }
          } else {
            if (micros() - nb_gtdelay >= (GT_LOW(GT_SPEED) - GT_OFFSET)) {  // wait for low pulse n to end
              nb_gtdelay = micros();                                        // non blocking micros() delay start again
              setPin(flag_NB);
              flag_NB = !flag_NB;
              _data >>= 1;
              byte_count++;
              break;
            }
          }
        } else {
          byte_count = 0;    // all 8 bytes were sent - reset counter
          _write_state = 5;  // go to next state
          nb_gtdelay = micros();
          break;
        }
        break;
      case 5:                                               //  Byte was sent
        if (micros() - nb_gtdelay >= (GT_LOW(GT_SPEED))) {  // Low Pulse (stop bit)
          transmitting = 0;                                 // transfer completed
          _write_state = 0;                                 // reset state machine to zero
          dataReady = true;   
          flag_NB = 0;                              // data was transferred - enable interrupts

#ifdef GT_CLI
#ifdef AVR
          SREG = sregSave;
#else
          interrupts();
#endif
#endif
        }
        break;
    }
    return dataReady;
  }