Mission 01 / 07
Dark Light
Sixteen dead control lines. Bring them back to life, one bit at a time.
On this page
01The situation
The Dark Light station has gone silent. Every control line is dead and every fault light glows red. Make the pins speak again.
02Why this matters
GPIO is how a chip touches the world. Every button you press and every LED you see on a device is a pin set as an input or an output.
- ButtonsA button is a pin set as an input. The chip reads it.
- LEDsAn LED is a pin set as an output. The chip drives it.
- Relays & motorsOne output pin can switch real power on and off.
03The idea in one picture
Think of it as: TRIS is the tap, PORT is the water. Open the tap (TRIS = 0) and switch the water on (PORT = 1); only then does it flow.
Go deeper
| TRIS bit | PORT bit | That pin… |
|---|---|---|
| 0 | 1 | is an output at 5 V (what this mission needs) |
| 0 | 0 | is an output held at 0 V |
| 1 | 0 or 1 | is an input: it listens and drives nothing |
04Your mission
- OSCCONStart the clock. Any speed works.
- TRISAMake every Port A pin an output.
- PORTADrive every Port A pin high.
- TRISBMake every Port B pin an output.
- PORTBDrive every Port B pin high.
Hint 1
Hint 2
0 means output. In PORT a 1 means 5 V. All eight bits, on both ports.Show the solution
- 1Step 1 — OSCCON (0x20)Set it to
0x05(0000 0101). Switch the internal oscillator on at 4 MHz (any speed wins). - 2Step 2 — TRISA (0x21)Set it to
0x00(0000 0000). Make every Port A pin an output. - 3Step 3 — PORTA (0x22)Set it to
0xFF(1111 1111). Drive every Port A pin to 5 V. - 4Step 4 — TRISB (0x23)Set it to
0x00(0000 0000). Make every Port B pin an output. - 5Step 5 — PORTB (0x24)Set it to
0xFF(1111 1111). Drive every Port B pin to 5 V. - 6Program & ExecutePress P to compile your configuration into machine code in ROM, then press E to run it. When every register matches you get Target Reached.
The same thing as a program (MOVLW loads a value into W, MOVWF copies W into a register):
MOVLW 0x05
MOVWF 0x20 ; OSCCONMOVLW 0x00
MOVWF 0x21 ; TRISAMOVLW 0xFF
MOVWF 0x22 ; PORTAMOVLW 0x00
MOVWF 0x23 ; TRISBMOVLW 0xFF
MOVWF 0x24 ; PORTBBit-by-bit breakdown
OSCCON0x20= 0x05
Switch the internal oscillator on at 4 MHz (any speed wins). 0x05 = 0000 0101 = SCS0 = 1, IRCF = 10
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Value | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| Field | — | IRCF | SCS0 | |||||
- IRCF (bits 2:1) =
10→ 4 MHz - SCS0 (bit 0) =
1→ Internal oscillator on - Every remaining bit is
0: those bits are not needed for this level, but they must stay clear for the value to match.
TRISA0x21= 0x00
Make every Port A pin an output. 0x00 = 0000 0000 = RA7…RA0 all 0
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Value | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Field | RA7 | RA6 | RA5 | RA4 | RA3 | RA2 | RA1 | RA0 |
- RA7…RA0 (bits 7:0) are all
0→ RAn is an output
PORTA0x22= 0xFF
Drive every Port A pin to 5 V. 0xFF = 1111 1111 = RA7…RA0 all 1
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Value | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Field | RA7 | RA6 | RA5 | RA4 | RA3 | RA2 | RA1 | RA0 |
- RA7…RA0 (bits 7:0) are all
1→ RAn drives 5 V (needs TRISA bit n = 0)
TRISB0x23= 0x00
Make every Port B pin an output. 0x00 = 0000 0000 = RB7…RB0 all 0
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Value | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Field | RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 |
- RB7…RB0 (bits 7:0) are all
0→ RBn is an output
PORTB0x24= 0xFF
Drive every Port B pin to 5 V. 0xFF = 1111 1111 = RB7…RB0 all 1
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Value | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Field | RB7 | RB6 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 |
- RB7…RB0 (bits 7:0) are all
1→ RBn drives 5 V (needs TRISB bit n = 0)
Try it: build the values
Flip the bits until each register matches the mission. It's practice only; nothing is saved.
2 of 5 registers match.
OSCCON 0x20
✗ Not yet – 2 bits differHex 0x00 Binary 0000 0000 Target 0x05 (0000 0101)
- IRCF (bits 2:1) = 00 → 1 MHz
- SCS0 (bit 0) = 0 → Internal oscillator not enabled
TRISA 0x21
✓ MATCHHex 0x00 Binary 0000 0000 Target 0x00 (0000 0000)
- RA7 (bit 7) = 0 → RA7 is an output
- RA6 (bit 6) = 0 → RA6 is an output
- RA5 (bit 5) = 0 → RA5 is an output
- RA4 (bit 4) = 0 → RA4 is an output
- RA3 (bit 3) = 0 → RA3 is an output
- RA2 (bit 2) = 0 → RA2 is an output
- RA1 (bit 1) = 0 → RA1 is an output
- RA0 (bit 0) = 0 → RA0 is an output
PORTA 0x22
✗ Not yet – 8 bits differHex 0x00 Binary 0000 0000 Target 0xFF (1111 1111)
- RA7 (bit 7) = 0 → RA7 low / not driving 5 V
- RA6 (bit 6) = 0 → RA6 low / not driving 5 V
- RA5 (bit 5) = 0 → RA5 low / not driving 5 V
- RA4 (bit 4) = 0 → RA4 low / not driving 5 V
- RA3 (bit 3) = 0 → RA3 low / not driving 5 V
- RA2 (bit 2) = 0 → RA2 low / not driving 5 V
- RA1 (bit 1) = 0 → RA1 low / not driving 5 V
- RA0 (bit 0) = 0 → RA0 low / not driving 5 V
TRISB 0x23
✓ MATCHHex 0x00 Binary 0000 0000 Target 0x00 (0000 0000)
- RB7 (bit 7) = 0 → RB7 is an output
- RB6 (bit 6) = 0 → RB6 is an output
- RB5 (bit 5) = 0 → RB5 is an output
- RB4 (bit 4) = 0 → RB4 is an output
- RB3 (bit 3) = 0 → RB3 is an output
- RB2 (bit 2) = 0 → RB2 is an output
- RB1 (bit 1) = 0 → RB1 is an output
- RB0 (bit 0) = 0 → RB0 is an output
PORTB 0x24
✗ Not yet – 8 bits differHex 0x00 Binary 0000 0000 Target 0xFF (1111 1111)
- RB7 (bit 7) = 0 → RB7 low / not driving 5 V
- RB6 (bit 6) = 0 → RB6 low / not driving 5 V
- RB5 (bit 5) = 0 → RB5 low / not driving 5 V
- RB4 (bit 4) = 0 → RB4 low / not driving 5 V
- RB3 (bit 3) = 0 → RB3 low / not driving 5 V
- RB2 (bit 2) = 0 → RB2 low / not driving 5 V
- RB1 (bit 1) = 0 → RB1 low / not driving 5 V
- RB0 (bit 0) = 0 → RB0 low / not driving 5 V
05How you know it worked
- 1The clock startsOSCCON switches the oscillator on and the CPU runs your program.Screenshot coming soon
- 2Pipes turn greenEvery pin you made an output gets a green output pipe.Screenshot coming soon
- 3The lights come onWith PORT high, all 16 fault-panel LEDs go from red to green.TARGET REACHEDScreenshot coming soon
Stuck?
- PORT changes nothing, pipes stay darkThe pins are still inputs. TRIS needs
0x00, not0xFF. - Pipes are green but the LEDs stay redOutputs are held low. Set PORT to
0xFF. - Only some LEDs turn greenSet all 8 bits (
0x0Flights only half), on both ports. - Nothing happens at allThe clock is off. OSCCON needs bit 0 set.
06Debrief
You just wrote the first lines of every firmware project.
Setting a pin's direction and level is embedded "hello world". Every blinking LED starts exactly here.
// the same idea in CTRISA = 0x00; // Port A: all outputsPORTA = 0xFF; // Port A: all highTRISB = 0x00; // Port B: all outputsPORTB = 0xFF; // Port B: all highOn a real chip the same switches can sit at different bit positions; its datasheet has the map. The idea is identical.