Skip to content

Auto-detect FPC-7519rev.b panel so old and new MagTags work without manual configuration#40

Merged
tyeth merged 3 commits into
adafruit:mainfrom
mikeysklar:fpc7519-support
May 22, 2026
Merged

Auto-detect FPC-7519rev.b panel so old and new MagTags work without manual configuration#40
tyeth merged 3 commits into
adafruit:mainfrom
mikeysklar:fpc7519-support

Conversation

@mikeysklar

@mikeysklar mikeysklar commented May 13, 2026

Copy link
Copy Markdown
Contributor

Newer MagTag units ship with a different display panel (FPC-7519rev.b) that needs different settings to render grayscale correctly. This updates the example to automatically detect which panel is installed and apply the right settings, so both old and new MagTags work without any manual configuration.

Newer MagTag units ship with FPC-7519rev.b display panels that need a
different VCOM voltage (0x24 vs 0x28), colstart=8, and a different
waveform LUT to render grayscale correctly.

The example now reads SSD1680 User ID register 0x2E via half-duplex
bitbang SPI on the MOSI line (same method as CircuitPython's built-in
MagTag board support) to auto-detect the panel before creating the
display, so both FPC-A005 and FPC-7519rev.b panels work out of the box
without any manual configuration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mikeysklar mikeysklar changed the title Add FPC-7519rev.b panel auto-detection to MagTag grayscale example Auto-detect FPC-7519rev.b panel so old and new MagTags work without manual configuration May 13, 2026
@brentru

brentru commented May 13, 2026

Copy link
Copy Markdown
Member

Woah, nice PR! Are you going to integrate this into the Adafruit Arduino SSD1680 library too?

@tyeth - we do this internally, in the WipperSnapper Display component, take a look at this interesting route!

)


def detect_ssd1680_panel():

@brentru brentru May 13, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a technical reason this function is sitting in the example?

I feel it'd be best as a method within the SSD1680's __init__ and having it auto-switch to the panel it detects. You'd be able to define the LUTs at module-level, too

@mikeysklar

Copy link
Copy Markdown
Contributor Author

top: MagTag SSD1680 (A005)
bottom: MagTag SSD1680 (7519rev.b)

Running PR code.

IMG_0341

@mikeysklar

mikeysklar commented May 13, 2026

Copy link
Copy Markdown
Contributor Author

@brentru -

The autodetect with USER IDs is something @dhalbert originally came up with a few months ago when the SSD1680s rev'd. I just dropped in some more init / LUT settings to clean up the fuzz issues (based on GxEPD2).

I submitted code in Adafruit_EPD pull #96 to support newer panels with the same initialization used here. I did not include autodetect for that library.

How about a detect_panel() at the module level to get it out of the example code? __init__ will be too late as FourWire will claim some pins I need to bitbang for USER ID.

@brentru

brentru commented May 13, 2026

Copy link
Copy Markdown
Member

How about a detect_panel() at the module level to get it out of the example code?

That's a good idea if you can not automatically switch, but the user will have to always know to call it.

@mikeysklar

mikeysklar commented May 13, 2026

Copy link
Copy Markdown
Contributor Author

It might be easier to leave detection in the example code for now.

Happy to consider other options, but I don't want to break away from the norm of how all other Adafruit display libraries work.

One other option to consider would be a wrapper with create_display() calling detect_panel(), but that is kind of funky too.

  display = adafruit_ssd1680.create_display(
      board.EPD_SCK, board.EPD_MOSI, board.EPD_CS,
      board.EPD_DC, board.EPD_RESET, board.EPD_BUSY,
      width=296, height=128, rotation=270, grayscale=True
  )

@brentru

brentru commented May 14, 2026

Copy link
Copy Markdown
Member

I'm just not sure if the LUTs should be in the example code, or the module...

@mikeysklar

Copy link
Copy Markdown
Contributor Author

Agreed. Let me pretty it up. I'll ping you once I've shuffled some code into the module.

FPC_A005_LUT, FPC7519_LUT, and detect_ssd1680_panel() moved from the
example into adafruit_ssd1680.py. Detection logic now defaults to
FPC-7519 settings for any unknown User ID, treating FPC-A005 (0x00)
as the legacy exception — forward-compatible with future panel revisions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mikeysklar

mikeysklar commented May 14, 2026

Copy link
Copy Markdown
Contributor Author

@brentru -

changes

  • moved the LUTs into the module
  • using detect_ssd1680_panel()
  • switched to newer panels (colstart=8 offset) being the default in case we get another address rev
  • shrink example ~185 -> ~64 LoC

testing

  • confirmed backwards compatibility with original example code and new library (no regression) for FPC-A005
  • older mono example still works calling SSD1680()
  • new display 0xca correctly detected
  • tested CP 10.2.1
  SSD1680 User ID first byte: 0x00
  Detected: FPC-A005 panel (legacy)
  refreshed
  SSD1680 User ID first byte: 0xca
  Detected: FPC-7519rev.b or newer panel
  refreshed

FPC-A005 (top)
FPC-7519rev.b (bottom)
webcam snap from this morning


Screenshot 2026-05-14 at 8 33 54 AM

@brentru brentru left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great - much cleaner example

@mikeysklar

Copy link
Copy Markdown
Contributor Author

Thank you. Glad we have something simple to get people going.

@ladyada

ladyada commented May 18, 2026

Copy link
Copy Markdown
Member

ok wanna merge this?

@mikeysklar

Copy link
Copy Markdown
Contributor Author

I'm ready to merge if @brentru is cool with it.

@brentru

brentru commented May 19, 2026 via email

Copy link
Copy Markdown
Member

@mikeysklar

Copy link
Copy Markdown
Contributor Author

@brentru can you pull the trigger on the merge. I do not have privs. Also will be submitting several more PRs next week for similar models.

@tyeth

tyeth commented May 22, 2026

Copy link
Copy Markdown
Member

Brent's away until Tuesday. Thanks for this Mikey, it'll be absorbed into wippersnapper too soon.

@tyeth tyeth merged commit f17e62d into adafruit:main May 22, 2026
1 check passed
@mikeysklar

mikeysklar commented May 22, 2026

Copy link
Copy Markdown
Contributor Author

Thx @tyeth.

Currently working on SSD1675A - SSD1683 to support grayscale. Just a heads up since you are updating Wippersnapper. Some of these might be of interest to you.

I'll be adding updates to this library and Adafruit_EPD.

Also a learn guide to explain the process.

# Product Chipset Status
#4195 2.13" FeatherWing (pre-Apr 2020) SSD1675A ✅ CP 4-gray working — pux4j LUT + VCOM=0x28
#4195 2.13" FeatherWing (post-Apr 2020) SSD1680 🔲 Unit not yet in hand
#4687 2.13" Pi Bonnet SSD1680 🔲 Not started
#4197 2.13" Breakout w/SRAM SSD1680 🔲 Not started (priority)
#6383 2.13" bare panel SSD1680 🔲 Not started
#4777 2.9" FeatherWing SSD1680 🔲 Not started (priority)
#4800 MagTag 2.9" SSD1680 ✅ Reference implementation (done)
#6381 4.2" bare panel SSD1683 🔲 Not started
#4196 1.54" Breakout w/SRAM + EYESPI SSD1681 🔲 Not started (OOS)

@tyeth

tyeth commented May 22, 2026

Copy link
Copy Markdown
Member

@mikeysklar I was going to ping you on that actually, I did a half understood greyscale implementation for the SSD1683, but wondered which was better having little blinka colour understanding, between swapping the LUT bits around for blinka from the ardu copy, or swapping the ram colour bank commands and using the arduino LUT, both resolved the issue. I figured I'd better grab the tri-color and understand it better before pinging anyone. That's just come into stock 3hrs ago, so next week I'll order one, or hope you tackle it before/for me 😁
adafruit/Adafruit_CircuitPython_SSD1683#2
[I have https://www.adafruit.com/product/6381 (greyscale), but wanted to confirm 3colour 6382 works too]

@mikeysklar

mikeysklar commented May 22, 2026

Copy link
Copy Markdown
Contributor Author

@tyeth - When I was working on the Magtag it came down to five settings. I got lucky since the GxEPD2_4G provided a great starting point with their LUT.

  • Two panel variants — same product, different PCB revisions; read a hardware ID byte at startup to tell them apart and load the right settings

  • Borrowed the waveform table from GxEPD2_4G — just had to flip the black/white rows since CircuitPython's color convention is opposite
    DC balance tweak — a specific alternating voltage pattern in the waveform eliminated pixel noise

  • VCOM voltage tuned by hand — the factory default caused ghosting; 0x24 was the sweet spot for this panel

  • Hard reset required before every refresh — the chip goes to sleep after each update; skip the reset and the first SPI command gets eaten

My strategy has been find a decent LUT to get things close and tune from there with Claude and a Webcam closed loop.

IMG_0309

adafruit-adabot pushed a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants