Trouble using PJRC ILI9341 touchscreen (alternate pins) w/ audio adapter

Status
Not open for further replies.

kd5rxt-mark

Well-known member
I have a PJRC ILI9341 touchscreen connected to a Teensy 4.0. I use an #ifdef statement to switch between the default pins & the alternate pins (for when using the ILI9341 touchscreen display & the Audio Adapter on the same Teensy) as follows"

Code:
// uncomment the next line to make use of the alternate pins (when used w/ Audio Adapter) for the display & touchscreen
#define USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN

#ifndef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// By default, the display uses hardware SPI, with pin #9 as DataCommand & pin #10 as ChipSelect
// MOSI=11, MISO=12, SCK=13
const int TFT_CHIP_SELECT = 10;
const int TFT_DATA_COMMAND = 9;
ILI9341_t3 tft = ILI9341_t3(TFT_CHIP_SELECT, TFT_DATA_COMMAND);
#endif

#ifdef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// Alternate ILI9341 display pins (when used w/ Audio Adapter) for optimized ILI9341_t3 library
#define TFT_DC      20
#define TFT_CS      21
#define TFT_RST    255  // 255 = unused, connect to 3.3V
#define TFT_MOSI     7
#define TFT_SCLK    14
#define TFT_MISO    12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
#endif

#ifndef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// By default, the touchscreen uses hardware SPI, with pin #9 as DataCommand & pin #8 as ChipSelect
// MOSI=11, MISO=12, SCK=13
#define TS_CS_PIN  8
#endif

#ifdef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// Alternate touchscreen pins (when used w/ Audio Adapter)
#define TS_CS_PIN  5
#endif

XPT2046_Touchscreen ts(TS_CS_PIN, 255);

Both the display & touchscreen work as expected when making use of the default/standard pin definitions. I am now attempting to make use the ILI9341 touchscreen using the alternate pins so I can use the Teensy 4.0 + ILI9341 touchscreen + Audio Adapter Rev D. I must be overlooking something simple as I am not able to get the same program (w/ alternate pins defined & rewired) to display anything. In addition, the onboard LED is still blinking (which appears like something is still using PIN 13 as a clock) as it did before the pin changes.

Here's the full program that I am playing with (including the pin modifications in place):

Code:
//
// TeensyChristmasTFT version 1.0 dated 12/24/2200 @1350
//    written by Mark J Culross, KD5RXT (kd5rxt@arrl.net)
//
// Teensy 4.0/4.1 Configuration:
//    Tools/Board:           "Teensy 4.0"
//    Tools/USB Type:        "Serial"
//    Tools/CPU Speed:       "600MHz"
//    Tools/Optimize:        "Fastest"
//    Tools/Keyboard Layout: "US English"
//    Tools/Port:            "COMx Serial (Teensy 4.0)"
//
//


#define VERSION1 F("TeensyChristmasTFT: Christmas tree & fireplace")
#define VERSION2 F("written by Mark J Culross (KD5RXT)")
#define VERSION3 F("version 1.0 dated 12/24/2020 @1350")

#include <ILI9341_t3.h>
#include <font_Arial.h> // from ILI9341_t3
#include <XPT2046_Touchscreen.h>
#include <SPI.h>

// This is calibration data for the raw touch data to the screen coordinates
// (NOTE: run the TFTcal-Teensy.ino sketch to determine the calibration values
//        for your specific touchscreen display, by touching the top-left
//        corner to find TS_MINX & TS_MINY, then rouching the bottom-right
//        corner to find TX_MAXX & TS_MAXY)
const int TS_MINX = 260;
const int TS_MINY = 220;
const int TS_MAXX = 3750;
const int TS_MAXY = 3740;

// uncomment the next line to make use of the alternate pins (when used w/ Audio Adapter) for the display & touchscreen
#define USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN

#ifndef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// By default, the display uses hardware SPI, with pin #9 as DataCommand & pin #10 as ChipSelect
// MOSI=11, MISO=12, SCK=13
const int TFT_CHIP_SELECT = 10;
const int TFT_DATA_COMMAND = 9;
ILI9341_t3 tft = ILI9341_t3(TFT_CHIP_SELECT, TFT_DATA_COMMAND);
#endif

#ifdef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// Alternate ILI9341 display pins (when used w/ Audio Adapter) for optimized ILI9341_t3 library
#define TFT_DC      20
#define TFT_CS      21
#define TFT_RST    255  // 255 = unused, connect to 3.3V
#define TFT_MOSI     7
#define TFT_SCLK    14
#define TFT_MISO    12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
#endif

#ifndef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// By default, the touchscreen uses hardware SPI, with pin #9 as DataCommand & pin #8 as ChipSelect
// MOSI=11, MISO=12, SCK=13
#define TS_CS_PIN  8
#endif

#ifdef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// Alternate touchscreen pins (when used w/ Audio Adapter)
#define TS_CS_PIN  5
#endif

XPT2046_Touchscreen ts(TS_CS_PIN, 255);
//XPT2046_Touchscreen ts(CS_PIN);  // Param 2 - NULL - No interrupts
//XPT2046_Touchscreen ts(CS_PIN, 255);  // Param 2 - 255 - No interrupts
//XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);  // Param 2 - Touch IRQ Pin - interrupt enabled polling


//
// The following pins are used in this project:
//
// PIN  D1  = (not used)
// PIN  D2  = (not used)
// PIN  D3  = (not used)
// PIN  D4  = (not used)
// PIN  D5  = (not used)
// PIN  D6  = (not used)
// PIN  D7  = (not used)
// PIN  D8  = TouchScreen chip select
// PIN  D9  = TFT/TS data/command select
// PIN D10  = TFT chip select
// PIN D11  = SPI MOSI (data in)
// PIN D12  = SPI MISO (data out)
// PIN D13  = SPI serial clock + on-board LED
// PIN  A0  = (not used)
// PIN  A1  = (not used)
// PIN  A2  = (not used)
// PIN  A3  = (not used)
// PIN  A4  = (not used)
// PIN  A5  = (not used)



// onboard LED on pin 13
#define LED_PIN 13

// keep track of whether the fireplace is ON or OFF
bool fire_on = true;


// The display size to use for the Christmas tree
const unsigned int tree_width = 220;
const unsigned int tree_height = 300;
unsigned int y_offset_tree = (320 - tree_height) / 2;
unsigned int x_offset_tree = (240 - tree_width) / 2;

// The display size to use for the fireplace
const unsigned int fire_width = 100;
const unsigned int fire_height = 100;
unsigned int x_offset_fire = (320 - fire_width) / 4;
unsigned int y_offset_fire = (240 - fire_height) / 2;

// These parameters control the fire appearance
#define HEAT_DEFAULT   50
#define COOL_DEFAULT   35   // 60 (coolest) to 10 (hottest)
#define FOCUS_DEFAULT  30
#define SPARK_DEFAULT  50

#define MAX_COOLING  10
#define MIN_COOLING  60

unsigned int heat            = HEAT_DEFAULT;
unsigned int focus           = FOCUS_DEFAULT;
unsigned int cool            = COOL_DEFAULT;
unsigned int spark_color     = SPARK_DEFAULT;

// Arrays for fire animation
unsigned char canvas[fire_width * fire_height];
extern const unsigned int fireColor[100];

boolean previously_touched = false;
boolean touch_triggered = false;

#define CUSTOM_FOREST_GREEN ILI9341_GREEN & 0xf1ff      // 0x006E33

#define NOT_FIRST_PASS      false
#define FIRST_PASS          true


typedef enum
{
   MODE_TREE=0, MODE_FIRE
}  OP_MODE;

OP_MODE mode = MODE_TREE;



void animateFire();
void drawTree(bool first_pass);
void draw_fire_spot(unsigned int x, unsigned int y, uint32_t firecolor);
void draw_tree_spot(unsigned int x, unsigned int y, unsigned int color_rgb);
void loop();
void setup();



void animateFire()
{
   unsigned int i, c, n, x, y;

   if (fire_on == true)
   {
      // Step 1: move all data up one line
      memmove(canvas + fire_width, canvas, fire_width * (fire_height - 1));
      memset(canvas, 0, fire_width);

      // Step 2: draw random heatspots on bottom line
      i = heat;
      if (i > fire_width-8) i = fire_width-8;
      while (i > 0) {
         x = random(fire_width - 2) + 1;
         if (canvas[x] == 0) {
            canvas[x] = spark_color;
            i--;
         }
      }

      // Step 3: interpolate
      for (y=0; y < fire_height; y++) {
         for (x=0; x < fire_width; x++) {
            c = canvas[y * fire_width + x] * focus;
            n = focus;
            if (x > 0) {
               c = c + canvas[y * fire_width + (x - 1)];
               n = n + 1;
            }
            if (x < fire_width-1) {
               c = c + canvas[y * fire_width + (x + 1)];
               n = n + 1;
            }
            if (y > 0) {
               c = c + canvas[(y -1) * fire_width + x];
               n = n + 1;
            }
            if (y < fire_height-1) {
               c = c + canvas[(y + 1) * fire_width + x];
               n = n + 1;
            }
            c = (c + (n / 2)) / n;
            i = (random(1000) * cool) / 10000;
            if (c > i) {
               c = c - i;
            } else {
               c = 0;
            }
            canvas[y * fire_width + x] = c;
         }
      }

      // Step 4: render canvas to LEDs
      for (y=0; y < fire_height; y++) {
         for (x=0; x < fire_width; x++) {
            c = canvas[((fire_height - 1) - y) * fire_width + x];
            draw_fire_spot(x, y, fireColor[c * 3]);
         }
      }
   } else {
      // turn off all LEDs
      for (y=0; y < fire_height; y++) {
         for (x=0; x < fire_width; x++) {
            draw_fire_spot(x, y, ILI9341_BLACK);
         }
      }
   }
}  // animateFire()


//
// draw a fireplace spot on the TFT & takes care of GRB32 to TFT_RGB conversion
//
void draw_fire_spot(unsigned int x, unsigned int y, uint32_t color_rgb32)
{
   // 32-bit GRB for LED = 8-bits GREEN + 8-bits RED + 8-bits BLUE
   // 16-bit RGB for TFT = 5-bits RED + 6-bits GREEN + 5-bits BLUE
   int tft_color_rgb = (((color_rgb32 & 0x1f0000) >> 5) + ((color_rgb32 & 0x003f00) >> 3)  + (color_rgb32 & 0x00001f)) & 0x00ffff;

   tft.drawPixel(x * 2 + x_offset_fire, y + y_offset_fire, tft_color_rgb);
}


//
// draw a spot on the TFT tree
//
void draw_tree_spot(unsigned int x, unsigned int y, unsigned int color_rgb)
{
   tft.drawPixel(x + x_offset_tree, y + y_offset_tree, color_rgb);
   tft.drawPixel(x + x_offset_tree + 1, y + y_offset_tree, color_rgb);
   tft.drawPixel(x + x_offset_tree, y + y_offset_tree + 1, color_rgb);
   tft.drawPixel(x + x_offset_tree + 1, y + y_offset_tree + 1, color_rgb);
}


// Draw the underlying tree
void drawTree(bool first_pass)
{
   for (unsigned int x = 0; x < tree_width; x++)
   {
      for  (unsigned int y = 0; y < tree_height; y++)
      {
         unsigned int leftside;
         unsigned int rightside;

         if (y < (tree_height - 16))
         {
            leftside = (float)(tree_width / 2) - (((float)(tree_height - y) / 2.5) * tree_width / tree_height) - ((tree_height - y) % ((tree_height - y) / 17));
            rightside = (float)(tree_width / 2) + (((float)(tree_height - y) / 2.5) * tree_width / tree_height) + ((tree_height - y) % ((tree_height - y) / 17));
         } else {
            leftside = (float)(tree_width / 2) - (((float)(tree_height - y) / 2.5) * tree_width / tree_height);
            rightside = (float)(tree_width / 2) + (((float)(tree_height - y) / 2.5) * tree_width / tree_height);
         }

         if ((x >= leftside) && (x <= rightside))
         {
            if (first_pass == true)
            {
               if (random(5) == 0)
               {
                  draw_tree_spot(x, y, CUSTOM_FOREST_GREEN);
               }
            } else {
               if (random(5000) == 0)
               {
                  switch(random(100))
                  {
                     case 0:
                     {
                        draw_tree_spot(x, y, ILI9341_RED);
                     }
                     break;

                     case 1:
                     {
                        draw_tree_spot(x, y, ILI9341_ORANGE);
                     }
                     break;

                     case 2:
                     {
                        draw_tree_spot(x, y, ILI9341_YELLOW);
                     }
                     break;

                     case 3:
                     {
                        draw_tree_spot(x, y, ILI9341_GREEN);
                     }
                     break;

                     case 4:
                     {
                        draw_tree_spot(x, y, ILI9341_BLUE);
                     }
                     break;

                     case 5:
                     {
                        draw_tree_spot(x, y, ILI9341_PURPLE);
                     }
                     break;

                     case 6:
                     {
                        draw_tree_spot(x, y, ILI9341_WHITE);
                     }
                     break;

                     default:
                     {
                        if (random(5) == 0)
                        {
                           draw_tree_spot(x, y, CUSTOM_FOREST_GREEN);
                        } else {
                           draw_tree_spot(x, y, ILI9341_BLACK);
                        }
                     }
                     break;
                  }
               }
            }
         } else {
            if (first_pass == true)
            {
               draw_tree_spot(x, y, ILI9341_BLACK);
            }
         }
      }
   }
}  // drawTree()


// Run repetitively
void loop()
{
   TS_Point p = ts.getPoint();

   // Scale from raw to tft values to expected width & height using the calibration #'s
   p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
   p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());

   if ((ts.touched() == false) && (previously_touched == true))
   {
      touch_triggered = true;
   }

   if (ts.touched() == true)
   {
      previously_touched = true;
   } else {
      previously_touched = false;
   }

   switch (mode)
   {
      case MODE_TREE:
      {
         drawTree(NOT_FIRST_PASS);

         if ((p.x >= 160) && (p.x <= 220) && (p.y >= 10) && (p.y <= 50))
         {
            if (touch_triggered == true)
            {
               touch_triggered = false;

               switch (mode)
               {
                  case MODE_TREE:
                  {
                     mode = MODE_FIRE;
                  }
                  break;

                  case MODE_FIRE:
                  {
                     mode = MODE_TREE;
                  }
                  break;
               }

               setup();
            }
         }
      }
      break;

      case MODE_FIRE:
      {
         animateFire();

         if ((p.x >= 0) && (p.x <= 40) && (p.y >= 100) && (p.y <= 140))
         {
            if (touch_triggered == true)
            {
               touch_triggered = false;

               fire_on = !fire_on;
            }
         } else {
            if ((p.x >= 260) && (p.x <= 300) && (p.y >= 100) && (p.y <= 140))
            {
               if (touch_triggered == true)
               {
                  touch_triggered = false;

                  switch (mode)
                  {
                     case MODE_TREE:
                     {
                        mode = MODE_FIRE;
                     }
                     break;

                     case MODE_FIRE:
                     {
                        mode = MODE_TREE;
                     }
                     break;
                  }

                  setup();
               }
            } else {
               if ((ts.touched() == true) & (p.y >= 180))
               {
                  cool = map(p.x, 0, 320, MIN_COOLING, MAX_COOLING);
   
                  tft.fillRect(0, 210, 320, 10, ILI9341_BLACK);
                  tft.fillRect(0, 221, 320, 10, ILI9341_BLACK);
   
                  tft.fillCircle(p.x, 220, 10, ILI9341_YELLOW);
                  tft.drawLine(0, 220, 320, 220, ILI9341_YELLOW);

                  tft.setTextColor(ILI9341_BLACK);
                  tft.setCursor(p.x - 8, 216);
                  tft.print(map(cool, 60, 10, 0, 100));
                  tft.print("%");

                  tft.setTextColor(ILI9341_GREEN);
                  tft.setCursor(5, 230);
                  tft.print("COOLER");

                  tft.setTextColor(ILI9341_RED);
                  tft.setCursor(280, 230);
                  tft.print("HOTTER");
               }
            }
         }
      }
      break;
   }
}  // loop()


// Run setup once
void setup()
{
   // initialize the serial port, then send out the firmware version string
   Serial.begin(9600);

   while (!Serial && (millis() <= 1000));

   Serial.println(VERSION1);
   Serial.println(VERSION2);
   Serial.println(VERSION3);
   Serial.println("");

   switch(mode)
   {
      case MODE_TREE:
      {
         delay(500);
         tft.begin();
         tft.setRotation(0);
         delay(100);
         ts.begin();
         ts.setRotation(0);

         tft.fillScreen(ILI9341_BLACK);

         drawTree(FIRST_PASS);

         tft.setRotation(2);

         tft.drawRect(170, 17, 50, 24, ILI9341_GREEN);
         tft.drawRect(172, 19, 46, 20, ILI9341_GREEN);

         tft.setTextColor(ILI9341_YELLOW);
         tft.setCursor(178, 25);
         tft.print("SWITCH");

         tft.setRotation(0);

         tft.drawRect(x_offset_tree - 1, y_offset_tree - 1, tree_width + 3, tree_height + 3, ILI9341_WHITE);
         tft.drawRect(x_offset_tree - 3, y_offset_tree - 3, tree_width + 7, tree_height + 7, ILI9341_WHITE);
      }
      break;

      case MODE_FIRE:
      {
         delay(500);
         tft.begin();
         tft.setRotation(1);
         delay(100);
         ts.begin();
         ts.setRotation(3);

         tft.fillScreen(ILI9341_BLACK);

         tft.setTextColor(ILI9341_GREEN);
         tft.setTextSize(1);
         tft.setCursor(22, 10);
         tft.print(VERSION1);

         tft.setTextColor(ILI9341_RED);
         tft.setCursor(52, 25);
         tft.print(VERSION2);

         tft.setTextColor(ILI9341_YELLOW);
         tft.setCursor(52, 40);
         tft.print(VERSION3);

         tft.drawRect(x_offset_fire - 1, y_offset_fire - 1, fire_width * 2 + 2, fire_height + 2, ILI9341_WHITE);
         tft.drawRect(x_offset_fire - 3, y_offset_fire - 3, fire_width * 2 + 6, fire_height + 6, ILI9341_WHITE);

         tft.setTextColor(ILI9341_YELLOW);
         tft.setCursor(52, 40);
         tft.print(VERSION3);

         tft.drawRect(0, 107, 50, 24, ILI9341_GREEN);
         tft.drawRect(2, 109, 46, 20, ILI9341_GREEN);

         tft.setTextColor(ILI9341_YELLOW);
         tft.setCursor(8, 115);
         tft.print("ON/OFF");

         tft.drawRect(260, 107, 50, 24, ILI9341_GREEN);
         tft.drawRect(262, 109, 46, 20, ILI9341_GREEN);

         tft.setTextColor(ILI9341_YELLOW);
         tft.setCursor(268, 115);
         tft.print("SWITCH");

         tft.drawLine(0, 220, 320, 220, ILI9341_YELLOW);

         tft.fillCircle(map (cool, MIN_COOLING, MAX_COOLING, 0, 320), 220, 10, ILI9341_YELLOW);

         tft.setTextColor(ILI9341_BLACK);
         tft.setCursor(map(cool, 60, 10, 0, 320) - 8, 216);
         tft.print(map(cool, 60, 10, 0, 100));
         tft.print("%");

         tft.setTextColor(ILI9341_GREEN);
         tft.setCursor(5, 230);
         tft.print("COOLER");

         tft.setTextColor(ILI9341_RED);
         tft.setCursor(280, 230);
         tft.print("HOTTER");
      }
      break;
   }
}  // setup()


// EOF PLACEHOLDER
 
Check the T_4.0 card or PJRC.com info. These alternate pins looks to exist on a T_3.2, but they are not available on a T_4.0 because of processor internal design.

Code:
#define TFT_MOSI     7
#define TFT_SCLK    14
 
Check the T_4.0 card or PJRC.com info. These alternate pins looks to exist on a T_3.2, but they are not available on a T_4.0 because of processor internal design.

Code:
#define TFT_MOSI     7
#define TFT_SCLK    14

@defragster:

Thanks for the reply. I have to admit that the text on the ILI9341 touchscreen display is very confusing/contradictory to me. In the "Connections" area, it says "This ILI3941 display works well with Teensy 4.0 and 4.1, using the standard connections shown in the table." In the "Usage With Audio Board Connections" area, it says "To use the ILI9341 display with the Audio Board, connect the signals using the alternate pins shown above." I guess that this second entry should really specify "To use the ILI9341 display with the Audio Board on a Teensy 3.x, connect the signals using the alternate pins shown above.", or maybe even better yet, "To use the ILI9341 display with the Audio Board, connect the signals using the alternate pins shown above. Note that this *does not* apply to the Teensy 4.x." I will add a comment in the "Web site could use a few updates :)" topic to see if @PaulStoffregen agrees that this needs to be clarified.

Thanks again & I'll go back to the standard wiring with the Teensy 4.0 + ILI9341 touchscreen + Audio Adapter Rev D, & hope to be pleasantly surprised !!

Mark J Culross
KD5RXT
 
As a follow-up, I was able to get the display & touchscreen working as before. I haven't tested the audio adapter yet, but that should "just work" as it has.

In the end, I ended up with the following pin assignments (only display CS & touchscreen CS changed from the Teensy 4.0 defaults) :

Code:
// uncomment the next line to make use of the alternate pins (when used w/ Audio Adapter) for the display & touchscreen
#define USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN

#ifndef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// By default, the display uses hardware SPI, with pin #9 as DataCommand & pin #10 as ChipSelect
// MOSI=11, MISO=12, SCK=13
const int TFT_CHIP_SELECT = 10;
#else
// Alternate display CS pin (when used w/ Audio Adapter)
const int TFT_CHIP_SELECT = 14;
#endif

const int TFT_DATA_COMMAND = 9;
ILI9341_t3 tft = ILI9341_t3(TFT_CHIP_SELECT, TFT_DATA_COMMAND);

#ifndef USE_ALTERNATE_PINS_FOR_ILI9341_TOUCHSCREEN
// By default, the touchscreen uses hardware SPI, with pin #9 as DataCommand & pin #8 as ChipSelect
// MOSI=11, MISO=12, SCK=13
#define TS_CS_PIN  8
#else
// Alternate touchscreen CS pin (when used w/ Audio Adapter)
#define TS_CS_PIN  5
#endif

XPT2046_Touchscreen ts(TS_CS_PIN, 255);


//
// The following pins are used in this project:
//
// PIN  D1  = (not used)
// PIN  D2  = (not used)
// PIN  D3  = (not used)
// PIN  D4  = (not used)
// PIN  D5  = TouchScreen chip select (alternate when used w/ audio adapter)
// PIN  D6  = Audio adapter memory chip select
// PIN  D7  = Audio adapter data in
// PIN  D8  = Audio adapter data out
// PIN  D9  = TFT/TS data/command select
// PIN D10  = Audio adapter SD card chip select
// PIN D11  = SPI MOSI (data in)
// PIN D12  = SPI MISO (data out)
// PIN D13  = SPI serial clock + on-board LED
// PIN  A0  = (D14) TFT chip select (alternate when used w/ audio adapter)
// PIN  A1  = Volume pot on audio adapter
// PIN  A2  = (not used)
// PIN  A3  = (not used)
// PIN  A4  = (D18) Audio adapter SDA (I2C control data)
// PIN  A5  = (D19) Audio adapter SCL (I2C control clock)

Thanks again @defragster for the help !!

Mark J Culross
KD5RXT
 
Status
Not open for further replies.
Back
Top