633 lines
12 KiB
Text
633 lines
12 KiB
Text
/////////////////////////////////
|
|
//
|
|
// FastLED6502
|
|
// by Mark Kriegsman
|
|
//
|
|
// Device driver and animation
|
|
// library for connecting addressable
|
|
// LED strips to an Apple II.
|
|
// The full "FastLED" library is
|
|
// available for Arduino and related
|
|
// microcontrollers.
|
|
//
|
|
/////////////////////////////////
|
|
//
|
|
// HOST COMPATIBILITY:
|
|
// Apples with 16-pin DIP "game ports"
|
|
// are fully supported; Apples with only
|
|
// 9-pin "game ports" are NOT supported.
|
|
//
|
|
// Apple ][ fully supported
|
|
// Apple ][+ fully supported
|
|
// Apple //e fully supported
|
|
//
|
|
// Apple //c and //c+ NOT supported
|
|
// as they lack the required 16-pin
|
|
// DIP game port for digital I/O.
|
|
//
|
|
// Apple //gs:
|
|
// motherboard game port IS supported
|
|
// back panel connector NOT supported
|
|
// See Notes section below.
|
|
//
|
|
// C64, PET, VIC-20, Atari400/800,
|
|
// NES, SYM, KIM-1, and other 6502
|
|
// systems are NOT supported at this
|
|
// time, but porting should be
|
|
// relatively easy for someone familiar
|
|
// with each target platform.
|
|
//
|
|
//
|
|
// LED STRIP COMPATIBILITY:
|
|
// In general, "four-wire" (clocked)
|
|
// LED strips can be supported, but
|
|
// "three-wire" (clockless) LED strips
|
|
// cannot be supported.
|
|
//
|
|
// APA102 tested & working
|
|
// Adafruit DotStar tested & working
|
|
// LPD8806 should work (untested)
|
|
// WS2801 should work (untested)
|
|
//
|
|
// WS2811/WS2812/NeoPixel can NOT work
|
|
// due to timing incompatibilities,
|
|
// namely that the 1MHz Apple is far
|
|
// too slow to drive them correctly.
|
|
//
|
|
//
|
|
// USAGE - HARDWARE:
|
|
// Connect an external power source to
|
|
// +5 and GND on the LED strip.
|
|
// Connect GND on the LED strip to GND
|
|
// on the game port connector (pin 8)
|
|
// Connect DATA IN on the LED strip to
|
|
// pin 12, 13, or 14 on the game port.
|
|
// Connect CLOCK IN on the LED strip to
|
|
// pin 5 (preferred), 12, 13, or 14 on
|
|
// the game port. Note: Apple //gs users
|
|
// cannot use pin 5.
|
|
//
|
|
//
|
|
// USAGE - SOFTWARE:
|
|
// At build time provide definitions for
|
|
// CHIPSET, DATA_PIN, CLOCK_PIN,
|
|
// NUM_LEDS, & BRIGHTNESS.
|
|
// Inside "Setup":
|
|
// Store LED count into
|
|
// FastLED_NumPixels,
|
|
// Store brightness into
|
|
// FastLED_Brightness
|
|
// Inside "Loop":
|
|
// Update the leds array, found in
|
|
// ledsR, ledsG, and ledsB
|
|
// Call FastLED_Show
|
|
// Jump back to top of "Loop"
|
|
//
|
|
//
|
|
// REFERENCE:
|
|
// FastLED_Show:
|
|
// display led array on LED strip
|
|
// FastLED_FillBlack:
|
|
// fill led array to black
|
|
// FastLED_FillSolid_RGB_AXY:
|
|
// fill led array with RGB color
|
|
// FastLED_FillSolid_Hue_X:
|
|
// fill led array with solid HSV Hue
|
|
// FastLED_Random8:
|
|
// return a pseudorandom number in A
|
|
// FastLED_FillRainbow_XY:
|
|
// fill led array with HSV rainbow
|
|
// starting at hue X, incrementing by
|
|
// huedelta Y each pixel.
|
|
// FastLED_SetHue_XY:
|
|
// set pixel Y to HSV hue X
|
|
// FastLED_Beat8:
|
|
// takes a speed increment in A, and
|
|
// returns a triangle wave in A.
|
|
//
|
|
//
|
|
// NOTES:
|
|
// For speed and size, there IS some
|
|
// self-modifying code in this
|
|
// library, so it cannot be burned
|
|
// into ROM without modification.
|
|
// Brightness control only works on
|
|
// APA102 at this point.
|
|
// Pin 15 is currently used as a
|
|
// 'frame start' signal for protocol
|
|
// diagnostics - makes frames more
|
|
// visible with an oscilloscope.
|
|
// If Pin 5 is specified for the CLOCK
|
|
// output pin, FastLED6502 will
|
|
// automatically use the high speed
|
|
// C040STROBE signal for clock. Note
|
|
// that the Apple //gs lacks this
|
|
// signal, even on the motherboard
|
|
// game port.
|
|
// The Apple joystick/mouse port on the
|
|
// rear of the //c, //c+, and //gs
|
|
// can NOT be used for LED connections
|
|
// because it lacks the necessary
|
|
// digital output pins.
|
|
// This library can drive 100 LED pixels
|
|
// at more than 30 frames per second.
|
|
//
|
|
//
|
|
// VERSION HISTORY
|
|
// 2015-02-07 - first version, by MEK
|
|
// assembled with xa65
|
|
// www.floodgap.com/retrotech/xa/
|
|
|
|
|
|
/////////////////////////////////
|
|
//
|
|
// ENTRY POINT
|
|
//
|
|
|
|
FastLED_Entry
|
|
jsr FastLED_FillBlack
|
|
jmp Setup
|
|
|
|
|
|
/////////////////////////////////
|
|
//
|
|
// FASTLED6502 GLOBALS
|
|
//
|
|
|
|
FastLED_NumPixels .byt NUM_LEDS
|
|
FastLED_Brightness .byt BRIGHTNESS
|
|
|
|
FastLED_RandomState .byt 17
|
|
FastLED_BeatState .byt 0
|
|
|
|
|
|
/////////////////////////////////
|
|
//
|
|
// API FUNCTIONS
|
|
//
|
|
|
|
FastLED_FillBlack
|
|
lda FastLED_NumPixels
|
|
pha
|
|
lda #255
|
|
sta FastLED_NumPixels
|
|
lda #0
|
|
tax
|
|
tay
|
|
jsr FastLED_FillSolid_RGB_AXY
|
|
jsr FastLED_Show
|
|
pla
|
|
sta FastLED_NumPixels
|
|
rts
|
|
|
|
|
|
FastLED_FillRainbow_XY
|
|
sty rbHueDelta
|
|
ldy #0
|
|
FR1
|
|
lda FastLED_RainbowR,x
|
|
sta ledsR,y
|
|
lda FastLED_RainbowG,x
|
|
sta ledsG,y
|
|
lda FastLED_RainbowB,x
|
|
sta ledsB,y
|
|
|
|
txa
|
|
clc
|
|
adc rbHueDelta
|
|
tax
|
|
|
|
iny
|
|
cpy FastLED_NumPixels
|
|
bne FR1
|
|
rts
|
|
|
|
rbHueDelta .byt 0
|
|
|
|
|
|
FastLED_SetHue_XY
|
|
lda FastLED_RainbowR,x
|
|
sta ledsR,y
|
|
lda FastLED_RainbowG,x
|
|
sta ledsG,y
|
|
lda FastLED_RainbowB,x
|
|
sta ledsB,y
|
|
rts
|
|
|
|
|
|
FastLED_FillSolid_RGB_AXY
|
|
sta ledsR
|
|
stx ledsG
|
|
sty ledsB
|
|
ldy #0
|
|
FillSolidRGBAXY1
|
|
lda ledsR
|
|
sta ledsR,y
|
|
lda ledsG
|
|
sta ledsG,y
|
|
lda ledsB
|
|
sta ledsB,y
|
|
iny
|
|
cpy FastLED_NumPixels
|
|
bne FillSolidRGBAXY1
|
|
rts
|
|
|
|
FastLED_FillSolid_Hue_X
|
|
ldy #0
|
|
FillSolidHX1
|
|
lda FastLED_RainbowR,x
|
|
sta ledsR,y
|
|
lda FastLED_RainbowG,x
|
|
sta ledsG,y
|
|
lda FastLED_RainbowB,x
|
|
sta ledsB,y
|
|
iny
|
|
cpy FastLED_NumPixels
|
|
bne FillSolidHX1
|
|
rts
|
|
|
|
|
|
; NOTE: USES SELF-MODIFYING CODE
|
|
FastLED_Random8
|
|
inc Random8GetLo
|
|
bne Random8Get
|
|
inc Random8GetHi
|
|
bne Random8Get
|
|
lda #$F8
|
|
sta Random8GetHi
|
|
lda #03
|
|
sta Random8GetLo
|
|
Random8Get
|
|
Random8GetLo = Random8Get + 1
|
|
Random8GetHi = Random8Get + 2
|
|
lda $F803
|
|
adc FastLED_RandomState
|
|
sta FastLED_RandomState
|
|
rts
|
|
|
|
|
|
FastLED_Beat8
|
|
clc
|
|
adc FastLED_BeatState
|
|
sta FastLED_BeatState
|
|
bit FastLED_BeatState
|
|
bmi FastLED_Beat8Neg
|
|
asl
|
|
rts
|
|
FastLED_Beat8Neg
|
|
lda #$ff
|
|
sec
|
|
sbc FastLED_BeatState
|
|
sbc FastLED_BeatState
|
|
rts
|
|
|
|
|
|
FastLED_Show
|
|
jmp CHIPSET
|
|
|
|
|
|
/////////////////////////////////
|
|
//
|
|
// HARDWARE INTERFACING
|
|
//
|
|
|
|
PINOFF_BASE = PIN15OFF
|
|
PINON_BASE = PIN15ON
|
|
|
|
#define PINON(P) PINON_BASE+((15-P)*2)
|
|
#define PINOFF(P) PINOFF_BASE+((15-P)*2)
|
|
|
|
DATAOFF = PINOFF(DATA_PIN)
|
|
DATAON = PINON(DATA_PIN)
|
|
CLKOFF = PINOFF(CLOCK_PIN)
|
|
CLKON = PINON(CLOCK_PIN)
|
|
|
|
// Special handling if CLOCK_PIN
|
|
// is 5: the C040STROBE line.
|
|
#if CLOCK_PIN = 5
|
|
#define CLOCK_ON bit PIN5STROBE
|
|
#define CLOCK_OFF
|
|
#else
|
|
#define CLOCK_ON bit CLKON
|
|
#define CLOCK_OFF bit CLKOFF
|
|
#endif
|
|
|
|
FRAMEON = PINON(15)
|
|
FRAMEOFF = PINOFF(15)
|
|
|
|
/////////////////////////////////
|
|
APA102
|
|
bit FRAMEON
|
|
jsr FastLED_Send00
|
|
jsr FastLED_Send00
|
|
jsr FastLED_Send00
|
|
jsr FastLED_Send00
|
|
|
|
lda FastLED_Brightness
|
|
lsr
|
|
lsr
|
|
lsr
|
|
ora #$E0
|
|
tax
|
|
|
|
ldy FastLED_NumPixels
|
|
APA102PX
|
|
txa
|
|
jsr FastLED_SendA
|
|
lda ledsB,y
|
|
jsr FastLED_SendA
|
|
lda ledsG,y
|
|
jsr FastLED_SendA
|
|
lda ledsR,y
|
|
jsr FastLED_SendA
|
|
dey
|
|
bne APA102PX
|
|
|
|
lda FastLED_NumPixels
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
tay
|
|
iny
|
|
APA102CL
|
|
jsr FastLED_SendFF
|
|
jsr FastLED_Send00
|
|
jsr FastLED_Send00
|
|
jsr FastLED_Send00
|
|
dey
|
|
bne APA102CL
|
|
bit FRAMEOFF
|
|
rts
|
|
|
|
/////////////////////////////////
|
|
LPD8806
|
|
bit FRAMEON
|
|
ldy FastLED_NumPixels
|
|
LPD8806PX
|
|
lda ledsG,y
|
|
lsr
|
|
ora #$80
|
|
jsr FastLED_SendA
|
|
lda ledsR,y
|
|
lsr
|
|
ora #$80
|
|
jsr FastLED_SendA
|
|
lda ledsB,y
|
|
lsr
|
|
ora #$80
|
|
jsr FastLED_SendA
|
|
dey
|
|
bne LPD8806PX
|
|
|
|
bit FRAMEOFF
|
|
rts
|
|
|
|
|
|
/////////////////////////////////
|
|
WS2801
|
|
bit FRAMEON
|
|
ldy FastLED_NumPixels
|
|
WS2801PX
|
|
lda ledsG,y
|
|
jsr FastLED_SendA
|
|
lda ledsR,y
|
|
jsr FastLED_SendA
|
|
lda ledsB,y
|
|
jsr FastLED_SendA
|
|
dey
|
|
bne WS2801PX
|
|
|
|
bit FRAMEOFF
|
|
rts
|
|
|
|
|
|
/////////////////////////////////
|
|
FastLED_SendFF
|
|
bit DATAON
|
|
jmp FastLED_SendXX
|
|
;
|
|
FastLED_Send00
|
|
bit DATAOFF
|
|
;
|
|
FastLED_SendXX
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
rts
|
|
|
|
FastLED_SendA
|
|
cmp #0
|
|
beq FastLED_Send00
|
|
cmp #$FF
|
|
beq FastLED_SendFF
|
|
|
|
asl
|
|
bcc S0x0
|
|
S0x1 bit DATAON
|
|
bcs S0xK
|
|
S0x0 bit DATAOFF
|
|
S0xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
asl
|
|
bcc S1x0
|
|
S1x1 bit DATAON
|
|
bcs S1xK
|
|
S1x0 bit DATAOFF
|
|
S1xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
asl
|
|
bcc S2x0
|
|
S2x1 bit DATAON
|
|
bcs S2xK
|
|
S2x0 bit DATAOFF
|
|
S2xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
asl
|
|
bcc S3x0
|
|
S3x1 bit DATAON
|
|
bcs S3xK
|
|
S3x0 bit DATAOFF
|
|
S3xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
asl
|
|
bcc S4x0
|
|
S4x1 bit DATAON
|
|
bcs S4xK
|
|
S4x0 bit DATAOFF
|
|
S4xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
asl
|
|
bcc S5x0
|
|
S5x1 bit DATAON
|
|
bcs S5xK
|
|
S5x0 bit DATAOFF
|
|
S5xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
asl
|
|
bcc S6x0
|
|
S6x1 bit DATAON
|
|
bcs S6xK
|
|
S6x0 bit DATAOFF
|
|
S6xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
asl
|
|
bcc S7x0
|
|
S7x1 bit DATAON
|
|
bcs S7xK
|
|
S7x0 bit DATAOFF
|
|
S7xK CLOCK_ON
|
|
CLOCK_OFF
|
|
|
|
rts
|
|
|
|
|
|
/////////////////////////////////
|
|
//
|
|
// Force page allignment for speed
|
|
// for leds array and Rainbow table
|
|
//
|
|
.dsb 256-(* & $FF),0
|
|
|
|
|
|
/////////////////////////////////
|
|
//
|
|
// LED ARRAY
|
|
//
|
|
|
|
ledsR .dsb 256,0
|
|
ledsG .dsb 256,0
|
|
ledsB .dsb 256,0
|
|
|
|
/////////////////////////////////
|
|
//
|
|
// HSV RAINBOW DEFINITION
|
|
//
|
|
// Generated directly from FastLED.
|
|
//
|
|
|
|
FastLED_RainbowR
|
|
.byt $FF,$FD,$FA,$F8,$F5,$F2,$F0,$ED
|
|
.byt $EA,$E8,$E5,$E2,$E0,$DD,$DA,$D8
|
|
.byt $D5,$D2,$D0,$CD,$CA,$C8,$C5,$C2
|
|
.byt $C0,$BD,$BA,$B8,$B5,$B2,$B0,$AD
|
|
.byt $AB,$AB,$AB,$AB,$AB,$AB,$AB,$AB
|
|
.byt $AB,$AB,$AB,$AB,$AB,$AB,$AB,$AB
|
|
.byt $AB,$AB,$AB,$AB,$AB,$AB,$AB,$AB
|
|
.byt $AB,$AB,$AB,$AB,$AB,$AB,$AB,$AB
|
|
.byt $AB,$A6,$A1,$9C,$96,$91,$8C,$86
|
|
.byt $81,$7C,$76,$71,$6C,$66,$61,$5C
|
|
.byt $56,$51,$4C,$47,$41,$3C,$37,$31
|
|
.byt $2C,$27,$21,$1C,$17,$11,$0C,$07
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$02,$05,$07,$0A,$0D,$0F,$12
|
|
.byt $15,$17,$1A,$1D,$1F,$22,$25,$27
|
|
.byt $2A,$2D,$2F,$32,$35,$37,$3A,$3D
|
|
.byt $3F,$42,$45,$47,$4A,$4D,$4F,$52
|
|
.byt $55,$57,$5A,$5C,$5F,$62,$64,$67
|
|
.byt $6A,$6C,$6F,$72,$74,$77,$7A,$7C
|
|
.byt $7F,$82,$84,$87,$8A,$8C,$8F,$92
|
|
.byt $94,$97,$9A,$9C,$9F,$A2,$A4,$A7
|
|
.byt $AB,$AD,$B0,$B2,$B5,$B8,$BA,$BD
|
|
.byt $C0,$C2,$C5,$C8,$CA,$CD,$D0,$D2
|
|
.byt $D5,$D8,$DA,$DD,$E0,$E2,$E5,$E8
|
|
.byt $EA,$ED,$F0,$F2,$F5,$F8,$FA,$FD
|
|
FastLED_RainbowG
|
|
.byt $00,$02,$05,$07,$0A,$0D,$0F,$12
|
|
.byt $15,$17,$1A,$1D,$1F,$22,$25,$27
|
|
.byt $2A,$2D,$2F,$32,$35,$37,$3A,$3D
|
|
.byt $3F,$42,$45,$47,$4A,$4D,$4F,$52
|
|
.byt $55,$57,$5A,$5C,$5F,$62,$64,$67
|
|
.byt $6A,$6C,$6F,$72,$74,$77,$7A,$7C
|
|
.byt $7F,$82,$84,$87,$8A,$8C,$8F,$92
|
|
.byt $94,$97,$9A,$9C,$9F,$A2,$A4,$A7
|
|
.byt $AB,$AD,$B0,$B2,$B5,$B8,$BA,$BD
|
|
.byt $C0,$C2,$C5,$C8,$CA,$CD,$D0,$D2
|
|
.byt $D5,$D8,$DA,$DD,$E0,$E2,$E5,$E8
|
|
.byt $EA,$ED,$F0,$F2,$F5,$F8,$FA,$FD
|
|
.byt $FF,$FD,$FA,$F8,$F5,$F2,$F0,$ED
|
|
.byt $EA,$E8,$E5,$E2,$E0,$DD,$DA,$D8
|
|
.byt $D5,$D2,$D0,$CD,$CA,$C8,$C5,$C2
|
|
.byt $C0,$BD,$BA,$B8,$B5,$B2,$B0,$AD
|
|
.byt $AB,$A6,$A1,$9C,$96,$91,$8C,$86
|
|
.byt $81,$7C,$76,$71,$6C,$66,$61,$5C
|
|
.byt $56,$51,$4C,$47,$41,$3C,$37,$31
|
|
.byt $2C,$27,$21,$1C,$17,$11,$0C,$07
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
FastLED_RainbowB
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$00,$00,$00,$00,$00,$00,$00
|
|
.byt $00,$02,$05,$07,$0A,$0D,$0F,$12
|
|
.byt $15,$17,$1A,$1D,$1F,$22,$25,$27
|
|
.byt $2A,$2D,$2F,$32,$35,$37,$3A,$3D
|
|
.byt $3F,$42,$45,$47,$4A,$4D,$4F,$52
|
|
.byt $55,$5A,$5F,$64,$6A,$6F,$74,$7A
|
|
.byt $7F,$84,$8A,$8F,$94,$9A,$9F,$A4
|
|
.byt $AA,$AF,$B4,$B9,$BF,$C4,$C9,$CF
|
|
.byt $D4,$D9,$DF,$E4,$E9,$EF,$F4,$F9
|
|
.byt $FF,$FD,$FA,$F8,$F5,$F2,$F0,$ED
|
|
.byt $EA,$E8,$E5,$E2,$E0,$DD,$DA,$D8
|
|
.byt $D5,$D2,$D0,$CD,$CA,$C8,$C5,$C2
|
|
.byt $C0,$BD,$BA,$B8,$B5,$B2,$B0,$AD
|
|
.byt $AB,$A9,$A6,$A4,$A1,$9E,$9C,$99
|
|
.byt $96,$94,$91,$8E,$8C,$89,$86,$84
|
|
.byt $81,$7E,$7C,$79,$76,$74,$71,$6E
|
|
.byt $6C,$69,$66,$64,$61,$5E,$5C,$59
|
|
.byt $55,$53,$50,$4E,$4B,$48,$46,$43
|
|
.byt $40,$3E,$3B,$38,$36,$33,$30,$2E
|
|
.byt $2B,$28,$26,$23,$20,$1E,$1B,$18
|
|
.byt $16,$13,$10,$0E,$0B,$08,$06,$03
|