Go Down

Topic: Using Trinket HID libraries in Arduino NANO (Read 227 times) previous topic - next topic

Suganesha

Hello everyone

Im a beginner so im sorry if there is any mistake in the question that i have asked.

I am making a USB Volume controller. I found a tutorial which is based on the Digispark attiny85 (Link: http://dangerousprototypes.com/forum/viewtopic.php?f=56&t=7654&p=62864#p62863 ). Since digispark has limited pins I was thinking of using an Arduino nano, as I require more pins because I thought of adding an extra encoder with other multimedia function. Also, it uses the neopixel 8-bit RGB ring for visual effects (Please watch the video for the visual effect : https://www.youtube.com/watch?v=r7PtrN89fg4 ). But I guess the TrinketHidCombo.H library does not work for Arduino. So I was wondering if anybody can help me out with the conversion of code from trinket to Arduino.

Thank You !!

CODE : (Written by Markus Gritsch from Dangerous prototypes. Open the above-mentioned link and find the download link for the code at the bottom of the page)

For quick reference:

#include <TrinketHidCombo.h>

#define TRINKET_PINx       PINB
#define PIN_ENCODER_A      0
#define PIN_ENCODER_B      2
#define PIN_ENCODER_SWITCH 5

// pos: 0 .. 3 * 255
void wheel( uint16_t pos, uint16_t & r, uint16_t & g, uint16_t & b )
{
   pos = 3 * 255 - pos;
   if ( pos < 255 ) {
      r = 255 - pos;
      g = 0;
      b = pos;
   } else if ( pos < 2 * 255 ) {
      pos -= 255;
      r = 0;
      g = pos;
      b = 255 - pos;
   } else {
      pos -= 2 * 255;
      r = pos;
      g = 255 - pos;
      b = 0;
   }
}

void boost_and_limit( uint16_t offset, uint16_t & r, uint16_t & g, uint16_t & b )
{
   r += offset;
   g += offset;
   b += offset;
   if ( r > 255 ) { r = 255; }
   if ( g > 255 ) { g = 255; }
   if ( b > 255 ) { b = 255; }
}

void send_twelve( uint8_t r, uint8_t g, uint8_t b )
{
   cli();
   for ( uint8_t i = 0; i < 12; ++i ) {
      sendPixel( r, g, b );
   }
   sei();
}

void setup()
{
   ledsetup();
   send_twelve( 0, 0, 0 );

   // Set pins as input with internal pull-up resistors enabled.
   pinMode( PIN_ENCODER_A, INPUT ); // The Digispark Arduino environment does not know
   pinMode( PIN_ENCODER_B, INPUT ); // about INPUT_PULLUP, so we use the old method:
   digitalWrite( PIN_ENCODER_A, HIGH );
   digitalWrite( PIN_ENCODER_B, HIGH );

   pinMode( PIN_ENCODER_SWITCH, INPUT );
   digitalWrite( PIN_ENCODER_SWITCH, HIGH );


   delay( 1000 ); // This helps to get the device enumerated after computer wake up.
   TrinketHidCombo.begin(); // Start the USB device engine and enumerate.
   while ( ! TrinketHidCombo.isConnected() ) {
      TrinketHidCombo.poll();
   }
}

void loop()
{
   // One loop takes about 8.6 us.
   // bitSet(PORTB, 1);
   // bitClear(PORTB, 1);

   static uint16_t offset = 0;
   static uint16_t ticks = 0;
   if ( ticks > 490 ) { // about 200 Hz (400 Hz disables the interrupt to often for V-USB)
      ticks = 0;
      static uint8_t divider = 0;

      static uint16_t pos = 2 * 255; // Start with blue.
      uint16_t r, g, b;
      wheel( pos, r, g, b );
      if ( ( divider & 0x0F ) == 15 ) { // Only advance the color every 16th iteration.  -> 12.5 Hz
         ++pos;                         // One full color cycle takes 255 * 3 / ( 200 / 16 ) = 61.2 s
         if ( pos > 3 * 255 ) {
            pos = 0;
         }
      }

      // Since we drive the LEDs only at 1/4 of the maximum brightness, and we use 8 bit color values,
      // we can use the lowest two color bits to dither the color values.  -> 50 Hz dither frequency.
      if ( ( r & 0x0003 ) > ( divider & 0x0003 ) ) { r += 4; }
      if ( ( g & 0x0003 ) > ( divider & 0x0003 ) ) { g += 4; }
      if ( ( b & 0x0003 ) > ( divider & 0x0003 ) ) { b += 4; }
      r >>= 2; g >>= 2; b >>= 2;

      ++divider; // Overflows from 255 to 0.

      boost_and_limit( offset >> 4, r, g, b );
      offset = ( offset >> 1 ) + ( offset >> 2 ) + ( offset >> 3 ) + ( offset >> 4 ) +
               ( offset >> 5 ) + ( offset >> 6 ); // 204 iterations

      // It took about 26 us to get here.
      send_twelve( r, g, b ); // Sending takes about 750 us.
   }
   ++ticks;

   // Poll the rotary encoder.
   static uint8_t enc_prev_pos = 3;
   uint8_t enc_cur_pos = 3;
   if ( bit_is_clear( TRINKET_PINx, PIN_ENCODER_A ) ) {
      enc_cur_pos &= ~( 1 << 0 );
   }
   if ( bit_is_clear( TRINKET_PINx, PIN_ENCODER_B ) ) {
      enc_cur_pos &= ~( 1 << 1 );
   }

   // https://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino
   if ( enc_cur_pos != enc_prev_pos ) {
      static uint8_t old_AB = 3;
      static int8_t encval = 0;
      static const int8_t enc_states[ 16 ] = { 0,-1, 1, 0,  1, 0, 0,-1,  -1, 0, 0, 1,  0, 1,-1, 0 };
      uint8_t AB = enc_cur_pos;
      old_AB <<= 2; // Remember previous state.
      old_AB |= AB;
      encval += enc_states[ old_AB & 0x0f ];
      if ( encval > 2 ) {
         offset = 1 << 12;
         TrinketHidCombo.pressMultimediaKey( MMKEY_VOL_UP );
         encval = 0;
      } else if ( encval < -2 ) {
         offset = 1 << 12;
         TrinketHidCombo.pressMultimediaKey( MMKEY_VOL_DOWN );
         encval = 0;
      } else if ( AB == 3 ) {
         encval = 0; // Bring the encval in sync with the detents in case of lost transitions.
      }
      enc_prev_pos = enc_cur_pos;
      delay( 2 ); // debounce
   }

   // The switch is active low.
   static bool sw_was_pressed = false;
   if ( bit_is_clear( TRINKET_PINx, PIN_ENCODER_SWITCH ) ) {
      if ( ! sw_was_pressed ) {
         sw_was_pressed = true;
         offset = 1 << 12;
         TrinketHidCombo.pressMultimediaKey( MMKEY_MUTE );
         delay( 20 ); // debounce
      }
   } else {
      if ( sw_was_pressed ) {
         sw_was_pressed = false;
         delay( 20 ); // debounce
      }
   }

   TrinketHidCombo.poll(); // Check if USB needs anything done, do every 10 ms or so.
}

Go Up