Crystal Focus logo
CRYSTALFOCUS.NET
GraFx beginner tutorial
COMMUNITY GUIDE
Bitmap blade animation for Crystal Focus X

GraFx Beginner's Tutorial for Crystal Focus X

A practical starter guide for setting up GraFx folders, drawing BMP animations, understanding frame order, and wiring GraFx into font_config.txt.
What you will learn
  • GraFx frame direction
  • BMP setup and dimensions
  • First main blade, ignition, and retraction
  • How grafx1.txt works
Who it is for
Audience
CFX users getting started with GraFx
Level
Beginner to intermediate
Use case
Building your first working GraFx set
Inside the tutorial
  • Folder structure
  • font_config.txt wiring
  • Extra effects like lockup and blaster
  • Quick reference section

GraFx Beginner's Tutorial for Crystal Focus X

What is GraFx?

GraFx (short for Graphics Efx) is the Crystal Focus X pixel blade animation system. Instead of generating blade effects algorithmically, GraFx plays BMP image files frame-by-frame on your LED blade. Each row of pixels in the BMP image becomes one animation frame, giving you full per-pixel color control over every moment of every effect — ignition, idle blade, retraction, lockup, clash, blaster, and more. On top of the bitmap colors, GraFx can also modify per-pixel behavior (pulsing, audio-reactivity, color-shifting, etc.) via accent types.

Think of it like a flipbook: you draw your animation as an image, and the CFX plays it back on your blade LEDs.


What You Need


Part 1: How GraFx Works (The Big Picture)

Your CFX SD card has a special folder for GraFx sets:

SD Card
└── extra/
    └── GRAFX/
        ├── 1-MyFirstGraFx/
        │   ├── grafx1.txt        <-- GraFx config file
        │   ├── normal1.bmp       <-- Main blade animation
        │   ├── poweron1.bmp      <-- Ignition animation
        │   ├── poweroff1.bmp     <-- Retraction animation
        │   └── ...more BMPs...
        ├── 2-AnotherStyle/
        │   ├── grafx1.txt
        │   ├── normal1.bmp
        │   └── ...
        └── 3-YetAnother/
            └── ...

Each numbered folder (the `1-`, `2-`, etc. prefix) is one complete GraFx set. The number prefix is how the CFX identifies and selects different GraFx sets. The name after the number is just for your reference.

Key concept: The number prefix (e.g. `1`, `2`, `3`) is what the firmware uses to select your GraFx folder. The text after the dash or underscore is for your own reference — the firmware needs it as a separator but does not use it for matching.


Part 2: Creating Your BMP Files

Image Dimensions

Image Format

How Frames Work

Because standard BMP files store pixel data bottom-up, the CFX reads frames from the bottom row to the top row:

Row 0 (bottom)  → Frame 1  (first frame shown)
Row 1           → Frame 2
Row 2           → Frame 3
...
Row N (top)     → Frame N+1  (last frame shown)

Important: This is standard BMP convention — pixel data starts at the bottom of the image. When you design your animation in an image editor, the bottom of the image is the first frame.

Each pixel in the row maps to one LED on your blade. Pixel 0 (left) is the base (emitter end), pixel N (right) is the tip.

Your First Main Blade BMP

Let's make a basic normal1.bmp for a 144-LED blade:

  1. Open your image editor
  2. Create a new image: 144 pixels wide × 20 pixels tall
  3. Paint each row with a solid color — try a bright blue #0044FF
  4. To make it interesting, vary the brightness slightly across rows for a subtle pulse effect
  5. Save as 24-bit BMP (uncompressed) named normal1.bmp

That's it — you now have a 20-frame main blade animation for the normal lit saber state!

Your First Ignition BMP: poweron1.bmp

For ignition, you want the blade to "grow" from base to tip. Remember: the bottom row is Frame 1.

  1. Create a new image: 144 wide × 30 tall
  2. Bottom row (Row 0): only the first few pixels colored (near the base), rest is black
  3. Row 1 (one row up): a few more pixels colored
  4. ...gradually fill more pixels across each row as you go upward...
  5. Top row (Row 29): all 144 pixels fully lit

Each row adds a bit more "blade" — creating an ignition scroll effect. The near-black pixels (transparent) leave the existing LED state untouched.

Retraction BMP: poweroff1.bmp

The reverse of ignition — the bottom row is fully lit, and as you move upward through the rows, pixels darken from tip to base.


Part 3: The grafx1.txt Config File

Every GraFx folder needs a file called grafx1.txt. This tells the CFX how to play your BMPs.

Basic Structure

The config file is organized into sections, one for each type of effect:

[LEDS]
delay=40
many=1

[POWERON]
delay=30
many=1

[POWEROFF]
delay=30
many=1

Section Names

Section What it controls BMP prefix
[LEDS] The normal main blade while the saber is on normal
[IDLE] Standby animation (when saber blade is OFF) idle
[POWERON] The ignition (power-on) animation poweron
[POWEROFF] The retraction (power-off) animation poweroff
[PREON] Pre-ignition effect (before ignition starts) preon
[POSTOFF] Post-retraction effect (residual glow, etc.) pstoff ⚠️
[LOCKUP] Lockup effect (blade-on-blade contact) lockup
[BLASTER] Blaster deflection bolt effect blaster
[FOREVER] Always-on fallback / background animation forever
Terminology note: In this tutorial, normal1.bmp refers to the saber's regular blade-on state and belongs to the [LEDS] section. That is different from the separate [IDLE] stage, which is used for standby behavior when the blade is off.

⚠️ POSTOFF naming: The section is called [POSTOFF] but the BMP file prefix is pstoff (shortened), not postoff. So your files should be named pstoff1.bmp, pstoff2.bmp, etc. This follows the legacy sound file naming convention.

FOREVER: Acts as a fallback sequence — when no other sequence is active, FOREVER plays. Commonly used for persistent accent effects on auxiliary strips (e.g. crystal chamber, BLASTER overlays).

Key Parameters

delay=

The time in milliseconds between each frame. It controls animation speed.

Important: delay also has a special auto-sync mode:

This makes delay=0 especially useful for GraFx sequences tied to a timed sound event:

For looping sections such as [LEDS], [IDLE], [FOREVER], and [LOCKUP], there is no sound duration context to calculate from. So for those sections, you should always set a real fixed delay value yourself instead of using delay=0.

many=

The number of BMP variants available for this sequence. If you have normal1.bmp and normal2.bmp, set many=2. The CFX will cycle through them sequentially (1 → 2 → 1 → 2 → ...) each time the sequence loads.

power=

Brightness for this sequence, from 0 to 100 (percent).

[LEDS]
delay=40
many=2
power=80

accents=

Defines how each individual LED behaves. This is a string where each character maps to one LED position on the strip.

Example: for a 10-LED strip, accents=aaaaaaaaaa means all pixels behave as regular sequenced accents and use the BMP colors directly.

Character Behavior
aRegular sequenced accent. Color comes directly from the BMP.
HColor-shifted pixel. Tints the gray/white parts of the BMP pixel toward the blade color from your color profile, while leaving saturated colors untouched. Controlled by colorshift_intensity= and colorshift_threshold=.
sMirror of the main blade. Uses the color of pixel #1 of the main blade.
@Audio flicker. Brightness follows audio volume, while color comes from the BMP and can change over time.
#Reverse audio flicker. Audio beat dims the pixel instead of brightening it. Color comes from the BMP.
mMorphing accent. Smoothly transitions from one state to the next over the stage duration.
rRandom sequenced accent. Changes randomly at the sequence frame rate using fully random RGB values.
RRandom sequenced accent using the color wheel at maximum brightness.
~Self-pulsing accent using the BMP color.
^Inverted self-pulsing accent using the BMP color.
BSelf-pulsing accent using the blade color from the active color profile.
IInverted self-pulsing accent using the blade color.
XSelf-pulsing accent using the crystal color from the active color profile.
LInverted self-pulsing accent using the crystal color.
*Audio flicker applied to the blade color.
$Audio flicker applied to the crystal color.
pPLI indicator on a single pixel. Shifts green → yellow → orange → red across the battery scale.
PPLI across a range of pixels. Turns BMP pixels on or off based on the battery scale.
MMagnetic level controls brightness using the blade color.
CMagnetic level controls brightness using the crystal color.
SMagnetic field controls blade-color self-pulsing.
TMagnetic field controls crystal-color self-pulsing.
AMagnetic score controls the brightness of the BMP sequence itself, revealing animated pixels as the field gets stronger.

Important: Always specify accents= explicitly for reliable behavior. The length of the string should match the number of LEDs for the strip that sequence is intended for.

Good beginner default: start with all a characters so every pixel simply follows the BMP. Then experiment with pulsing, audio flicker, PLI, or magnetic-driven accents once the base animation is working.

colorshift_intensity=

When using H type pixels, this controls how much the BMP color gets blended toward the blade color (0–255). Higher values mean more blade color.

colorshift_threshold=

Minimum pixel brightness before color shifting kicks in. Keeps dark areas in the BMP from being shifted.


Part 4: Setting Up the SD Card

Step 1: Create the GraFx Folder

On your SD card, create this folder structure:

extra/
└── GRAFX/
    └── 1-MyGraFx/

Step 2: Add Your BMP Files

Copy your BMP files into the folder:

extra/GRAFX/1-MyGraFx/
├── grafx1.txt
├── normal1.bmp
├── poweron1.bmp
└── poweroff1.bmp

Step 3: Create the grafx1.txt File

Create a text file named grafx1.txt inside that same folder:

[LEDS]
delay=40
many=1

[POWERON]
delay=25
many=1

[POWEROFF]
delay=25
many=1

Step 4: Tell Your Font to Use GraFx

Open your saber's config.txt and add/edit these lines in the relevant Blade Profile:

## GRAFX BLADE SETUP
## Set the main blade effect to GraFx mode (17 = GRAFX_FX)
unstable=17

## Point to GraFx folder #1 (the "1-" folder)
style_grafx1=1

## Set power-on animation to GraFx mode (10 = POWERON_STYLE_GRAFX)
style_pon=10

## Set power-off animation to GraFx mode (11 = POWEROFF_STYLE_GRAFX)
style_poff=11

What Those Numbers Mean

The firmware identifies styles by number. Here are the GraFx style numbers for each effect:

Config Key GraFx Value What It Does
unstable= 17 Main blade effect = GraFx
style_pon= 10 Power-on animation = GraFx
style_poff= 11 Power-off animation = GraFx
style_lockup= 7 Lockup effect = GraFx
style_blaster= 9 Blaster bolt = GraFx
style_clash= 8 Clash effect = GraFx
style_drag= 5 Drag effect = GraFx
style_preon= 4 Pre-ignition = GraFx
style_postoff= 4 Post-retraction = GraFx

You only need to set the ones you actually want to use GraFx for in that blade profile. The others can use the regular built-in effects.


Part 5: A Complete Minimal Example

SD Card Layout

SD Card/
├── 1-MyFont/               <-- your sound font folder
│   ├── font_config.txt
│   ├── hum.wav
│   ├── poweron.wav
│   ├── poweroff.wav
│   ├── clash1.wav
│   └── ...
└── extra/
    └── GRAFX/
        └── 1-BlueFire/
            ├── grafx1.txt
            ├── normal1.bmp
            ├── poweron1.bmp
            └── poweroff1.bmp

config.txt Blade Profile

unstable=17
style_grafx1=1
style_pon=10
style_poff=11

Important: These style parameters belong to the relevant Blade Profile in config.txt. They are not part of font_config.txt.

grafx1.txt

[LEDS]
delay=40
many=1

[POWERON]
delay=25
many=1

[POWEROFF]
delay=30
many=1

BMP Files (for a 144-LED blade)


Part 6: Multiple Blades (Auxiliary & Quillon)

If your saber has multiple pixel strips (main blade, aux strip, quillon / crossguard), you can assign different GraFx sets to each:

Config Key Strip
style_grafx1= Main blade
style_grafx2= Auxiliary strip
style_grafx3= Quillon / crossguard

Each can point to a different numbered GraFx folder, or the same one.


Part 7: Adding More Effects

Once you're comfortable with the basics, you can add GraFx animations for all the other effects.

Adding a Lockup GraFx

  1. Create lockup1.bmp in your GraFx folder (e.g. 144 × 10 pixels)
  2. Add to grafx1.txt:
    [LOCKUP]
    delay=40
    many=1
    
  3. Add to the relevant blade profile in config.txt:
    style_lockup=7
    

Adding a Blaster GraFx

  1. Create blaster1.bmp in your GraFx folder
  2. Add to grafx1.txt:
    [BLASTER]
    delay=20
    many=1
    
  3. Add to the relevant blade profile in config.txt:
    style_blaster=9
    

Adding Pre-On / Post-Off

  1. Create preon1.bmp and/or pstoff1.bmp
  2. Add to grafx1.txt:
    [PREON]
    delay=30
    many=1
    
    [POSTOFF]
    delay=40
    many=1
    
  3. Add to the relevant blade profile in config.txt:
    style_preon=4
    style_postoff=4
    

Adding Multiple Variants

Want some variety? Create multiple BMPs for the same effect:

normal1.bmp
normal2.bmp
normal3.bmp

Then set many=3 in the [LEDS] section. The CFX cycles through them sequentially (1 → 2 → 3 → 1 → ...) each time the sequence is triggered.


Part 8: Using Themes

If your saber uses themes (multiple visual themes per font), each theme can have its own GraFx library. The CFX looks for GraFx folders inside the theme's folder first:

1-MyFont/
└── 1-ThemeName/
    └── extra/
        └── GRAFX/
            └── 1-ThemedGraFx/
                ├── grafx1.txt
                └── ...

If a themed GraFx folder isn't found, the CFX falls back to the global /extra/GRAFX/ folder.


Tips & Troubleshooting

Image Tips

Common Mistakes

Testing


Quick Reference Card

Folder Structure

extra/GRAFX/<N>-<name>/grafx1.txt   (config)
extra/GRAFX/<N>-<name>/normal1.bmp  (main blade)
extra/GRAFX/<N>-<name>/poweron1.bmp (ignition)
extra/GRAFX/<N>-<name>/poweroff1.bmp(retraction)
extra/GRAFX/<N>-<name>/lockup1.bmp  (lockup)
extra/GRAFX/<N>-<name>/clash1.bmp   (clash)
extra/GRAFX/<N>-<name>/blaster1.bmp (blaster)
extra/GRAFX/<N>-<name>/preon1.bmp   (pre-ignition)
extra/GRAFX/<N>-<name>/pstoff1.bmp  (post-retraction)
extra/GRAFX/<N>-<name>/idle1.bmp    (standby, blade OFF)
extra/GRAFX/<N>-<name>/forever1.bmp (looping background)

font_config.txt Keys

unstable=17           # Main blade = GraFx
style_grafx1=<N>      # Which GRAFX folder (by number prefix)
style_grafx2=<N>      # Aux strip GRAFX folder
style_grafx3=<N>      # Quillon GRAFX folder
style_pon=10          # Power-on = GraFx
style_poff=11         # Power-off = GraFx
style_lockup=7        # Lockup = GraFx
style_clash=8         # Clash = GraFx
style_blaster=9       # Blaster = GraFx
style_drag=5          # Drag = GraFx
style_preon=4         # Pre-on = GraFx
style_postoff=4       # Post-off = GraFx

grafx1.txt Sections & Parameters

[LEDS]                # Main blade while ON
[IDLE]                # Standby (blade OFF)
[POWERON]             # Ignition
[POWEROFF]            # Retraction
[PREON]               # Pre-ignition
[POSTOFF]             # Post-retraction
[LOCKUP]              # Lockup
[BLASTER]             # Blaster
[FOREVER]             # Continuous loop

# Parameters (per section):
delay=<ms>            # Frame delay in milliseconds
many=<count>          # Number of BMP variants
power=<0-100>         # Brightness percentage
accents=<string>      # Per-LED behavior characters
colorshift_intensity=<0-255>
colorshift_threshold=<0-255>

Happy saber building!