# Proxmark3 LED PWM Implementation - Complete

**Status:** ✅ Implemented, Flashed, and Tested
**Date:** 2025-12-02
**Hardware:** Proxmark3 Easy
**Firmware:** Iceman/master/4fa8f27-dirty

## Summary

Successfully implemented two-channel hardware PWM brightness control for LED A and LED B on Proxmark3 Easy, along with basic on/off/toggle control for all LEDs.

## Hardware Configuration

### Proxmark3 Easy LED Mappings

| LED | Color  | GPIO Pin | PWM Channel | Brightness Control | Position |
|-----|--------|----------|-------------|--------------------|----------|
| A   | Green  | PA0      | PWM0        | ✅ 0-100%          | 1st (left) |
| B   | Blue   | PA2      | PWM2        | ✅ 0-100%          | 4th (right) |
| C   | Orange | PA9      | None        | On/Off only        | 2nd |
| D   | Red    | PA8      | None        | On/Off only        | 3rd |

**Physical LED order (left to right):** Green, Orange, Red, Blue

### PWM Channel Allocation

- **PWM0** → LED A brightness control (PA0)
- **PWM1** → System timing functions (moved from PWM0)
- **PWM2** → LED B brightness control (PA2)
- **PWM3** → Unused

## Command Interface

### Basic LED Control (All LEDs)

```bash
hw led --led a --on                     # Turn on LED A
hw led --led b --off                    # Turn off LED B
hw led --led c,d --toggle               # Toggle LEDs C and D
hw led --led all --off                  # Turn off all LEDs
```

### PWM Brightness Control (LED A and B only)

```bash
hw led --led a --brightness 50          # LED A at 50% brightness
hw led --led b --brightness 75          # LED B at 75% brightness
hw led --led a,b --brightness 25        # Both LEDs at 25% brightness
hw led --led a --brightness 0           # LED A off via PWM
hw led --led b --brightness 100         # LED B at full brightness
```

### Multi-Device Identification Examples

```bash
# Device 1 - Dim green
hw led --led a --brightness 20

# Device 2 - Medium blue
hw led --led b --brightness 50

# Device 3 - Bright green
hw led --led a --brightness 80

# Device 4 - Mixed (40% green + 60% blue)
hw led --led a --brightness 40
hw led --led b --brightness 60
```

## Implementation Details

### Files Modified (7 files)

**Firmware:**
1. `common_arm/ticks.c` - Moved SpinDelay timing from PWM0 → PWM1
2. `common_arm/usb_cdc.c` - Moved USB timing from PWM0 → PWM1
3. `armsrc/util.c` - Moved button timing PWM0 → PWM1, added PWM LED functions
4. `armsrc/util.h` - Added function declarations
5. `armsrc/appmain.c` - Added CMD_LED_CONTROL handler

**Protocol:**
6. `include/pm3_cmd.h` - Added CMD_LED_CONTROL (0x011A) and payload structure

**Client:**
7. `client/src/cmdhw.c` - Added `hw led` command with CLIParser

### Protocol Definition

```c
// Command ID
#define CMD_LED_CONTROL  0x011A

// Payload structure
typedef struct {
    uint8_t led;        // LED bitmask: LED_A=1, LED_B=2, LED_C=4, LED_D=8
    uint8_t action;     // 0=off, 1=on, 2=toggle, 3=pwm
    uint8_t brightness; // 0-100 (for action=3 PWM mode only)
} PACKED payload_led_control_t;
```

### PWM Functions (armsrc/util.c)

```c
void led_set_pwm_brightness(uint8_t led, uint8_t brightness);
void led_pwm_disable(uint8_t led);
```

**PWM Configuration:**
- Frequency: 48 kHz (MCK / 1000)
- Resolution: 1000 steps (0.1% precision, exposed as 0-100%)
- Duty cycle: Inverted for active-low LEDs
- CPU overhead: Zero (hardware-controlled)

### Action Modes

| Action | Value | Description |
|--------|-------|-------------|
| Off    | 0     | Turn LED off (disables PWM if active) |
| On     | 1     | Turn LED on at full brightness (disables PWM) |
| Toggle | 2     | Toggle LED state (disables PWM) |
| PWM    | 3     | Set PWM brightness (0-100%, LED A/B only) |

## Build Configuration

### Required Makefile.platform Settings

```makefile
PLATFORM=PM3GENERIC
LED_ORDER=PM3EASY
```

**IMPORTANT:** The `LED_ORDER=PM3EASY` flag is **required** for PM3 Easy hardware. Without it, LED B will be mapped to PA8 (no PWM) instead of PA2 (PWM2).

### Build Commands

```bash
cd .pm3-test/proxmark3

# Ensure correct platform settings
cat > Makefile.platform << EOF
PLATFORM=PM3GENERIC
LED_ORDER=PM3EASY
EOF

# Build
SKIPQT=1 CFLAGS="-Wno-error=bad-function-cast" make all

# Flash
./pm3-flash-all
```

## Testing Results

✅ **All Tests Passed:**
- Firmware compiled: 359,015 bytes (68% of 512KB)
- Flashed successfully to Proxmark3 Easy
- PWM LED commands working correctly
- Timing functions verified (`hw status` passed)
- No interference with RF operations
- Button functionality intact

## Technical Notes

### PWM Channel Reallocation

The original Proxmark3 firmware used PWM0 for timing functions. To enable LED A brightness control, all timing functions were moved from PWM0 to PWM1:

- `SpinDelayUsPrecision()` - High precision delays
- `SpinDelayUs()` - Standard delays
- `BUTTON_CLICKED()` / `BUTTON_HELD()` - Button debouncing
- USB timing functions

This change has **zero performance impact** and frees PWM0 for LED control.

### Compatibility

**Hardware Compatibility:**
- ✅ PM3 Easy (PA0=PWM0, PA2=PWM2)
- ⚠️ Other PM3 variants - PWM support depends on LED pin mapping
- Without `LED_ORDER=PM3EASY`, LED B may not support PWM

**Backward Compatibility:**
- ✅ Fully backward compatible with existing firmware
- ✅ New `hw led` command co-exists with other hw commands
- ✅ No changes to existing command behavior

### Performance Impact

**Expected impact: ZERO**
- PWM channels operate independently in hardware
- No CPU overhead once configured
- No timer interrupts needed
- No interference with RF operations
- Timing functions work identically on PWM1

## Future Enhancements

Potential improvements if needed:
1. Software PWM for LED C/D (more complex, CPU overhead)
2. Fade in/out effects using gradual brightness changes
3. Brightness presets (low, medium, high)
4. Auto-dim after inactivity for power saving

## References

- [LED_MAPPINGS.md](LED_MAPPINGS.md) - LED color and pin reference
- PM3_EASY_PWM_FINAL.md - Original design document (archived)
- PWM_ENHANCEMENT_COMPLETE.md - Development notes (archived)

---

**Implementation by:** Claude Code
**Hardware Tested:** Proxmark3 Easy
**Firmware Version:** Iceman/master/4fa8f27-dirty
