I/O Pins

TODO

Each I/O pin has the following inputs:

And the following outputs:

Pin Fields

Many instructions that operate on pins will take a Pin Field for a parameter. A Pin Field is an 11-bit value consisting of a 6-bit base pin number and a 5-bit field length (where 0 means 1 pin). Any pin number 0..63 can be interpreted as a pin field consisting of just that pin. Larger pinfields can be created using an expression like base_pin + (extra_pins >> 6) (there also exists a addpins infix operator as a shorthand for this).

A pin field may address up to 32 pins, but they can not cross the Port A / Port B boundary between pins 31 and 32 and will instead wraparound inside the base pin's port.

All instructions that support pin fields also support overriding the field length using SETQ. In this case the field length in the actual operand is ignored.

A Pin Field is similar to a Bit Field (Link TODO), but not interchangeable.

Examples: - 1 addpins 0 or just 1 refers just to Pin 1 - 1 addpins 1 refers just to Pins 1 and 2 - 32 addpins 7 refers to pins 32..39 - 31 addpins 1 refers to pins 31 and 0 (intra-port wraparound)

Diagram

TODO: Transparent version

I/O Instructions

{ SETQ {#}Q }
DRVL {#}D {WCZ} - Set pin OUT low and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011000 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DRVH {#}D {WCZ} - Set pin OUT high and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011001 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DRVNOT {#}D {WCZ} - Invert pin OUT and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011111 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DRVRND {#}D {WCZ} - Randomize pin OUT and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011110 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DRVC {#}D {WCZ} - Set pin OUT to C and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011010 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DRVNC {#}D {WCZ} - Set pin OUT to !C and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011011 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DRVZ {#}D {WCZ} - Set pin OUT to Z and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011100 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DRVNZ {#}D {WCZ} - Set pin OUT to !Z and set DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001011101 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTL {#}D {WCZ} - Set pin OUT low and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010000 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTH {#}D {WCZ} - Set pin OUT high and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010001 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTNOT {#}D {WCZ} - Invert pin OUT and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010111 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTRND {#}D {WCZ} - Randomize pin OUT and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010110 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTC {#}D {WCZ} - Set pin OUT to C and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010010 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTNC {#}D {WCZ} - Set pin OUT to !C and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010011 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTZ {#}D {WCZ} - Set pin OUT to Z and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010100 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
FLTNZ {#}D {WCZ} - Set pin OUT to !Z and set DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001010101 DIRx* + OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTL {#}D {WCZ} - Set pin OUT low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001000 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTH {#}D {WCZ} - Set pin OUT high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001001 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTNOT {#}D {WCZ} - Invert pin OUT

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001111 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTRND {#}D {WCZ} - Randomize pin OUT

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001110 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTC {#}D {WCZ} - Set pin OUT to C

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001010 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTNC {#}D {WCZ} - Set pin OUT to !C

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001011 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTZ {#}D {WCZ} - Set pin OUT to Z

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001100 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
OUTNZ {#}D {WCZ} - Set pin OUT to !Z

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001001101 OUTx OUT[D[5:0]] OUT[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRL {#}D {WCZ} - Set pin DIR low

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000000 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRH {#}D {WCZ} - Set pin DIR high

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000001 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRNOT {#}D {WCZ} - Invert pin DIR

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000111 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRRND {#}D {WCZ} - Randomize pin DIR

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000110 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRC {#}D {WCZ} - Set pin DIR to C

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000010 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRNC {#}D {WCZ} - Set pin DIR to !C

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000011 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRZ {#}D {WCZ} - Set pin DIR to Z

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000100 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

{ SETQ {#}Q }
DIRNZ {#}D {WCZ} - Set pin DIR to !Z

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000101 DIRx DIR[D[5:0]] DIR[D[5:0]] 2 2 No

TESTP {#}D WC/WZ - Test pin

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000000 none IN[D[5:0]] IN[D[5:0]] 2 2 No

TESTP {#}D ANDC/ANDZ - Test pin (AND with current flag)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000010 none C/Z AND IN[D[5:0]] C/Z AND IN[D[5:0]] 2 2 No

TESTP {#}D ORC/ORZ - Test pin (OR with current flag)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000100 none C/Z OR IN[D[5:0]] C/Z OR IN[D[5:0]] 2 2 No

TESTP {#}D XORC/XORZ - Test pin (XOR with current flag)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000110 none C/Z XOR IN[D[5:0]] C/Z XOR IN[D[5:0]] 2 2 No

TESTP reads the IN state (0/1) of a pin designated by Source and either stores it as-is, or bitwise ANDs, ORs, or XORs it into the C or Z flag.

Source[5:0] indicates the pin number (0–63) to test.

If the WC or WZ effect is specified, the C or Z flag is overwritten with the state of the pin.

If the ANDC or ANDZ effect is specified, the C or Z flag is bitwise ANDed with the state of the pin.

If the ORC or ORZ effect is specified, the C or Z flag is bitwise ORed with the state of the pin.

If the XORC or XORZ effect is specified, the C or Z flag is bitwise XORed with the state of the pin.

See also TESTPN.

TESTPN {#}D WC/WZ - Test pin (negative)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000001 none !IN[D[5:0]] !IN[D[5:0]] 2 2 No

TESTPN {#}D ANDC/ANDZ - Test pin (negative, AND with current flag)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000011 none C/Z AND !IN[D[5:0]] C/Z AND !IN[D[5:0]] 2 2 No

TESTPN {#}D ORC/ORZ - Test pin (negative, OR with current flag)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000101 none C/Z OR !IN[D[5:0]] C/Z OR !IN[D[5:0]] 2 2 No

TESTPN {#}D XORC/XORZ - Test pin (negative, XOR with current flag)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZL DDDDDDDDD 001000111 none C/Z XOR !IN[D[5:0]] C/Z XOR !IN[D[5:0]] 2 2 No

TESTPN reads the IN state (0/1) of a pin designated by Source, inverts the result, and either stores it (the inverse value) as-is, or bitwise ANDs, ORs, or XORs it into the C or Z flag.

Source[5:0] indicates the pin number (0–63) to test and invert.

If the WC or WZ effect is specified, the C or Z flag is overwritten with the inverse state of the pin.

If the ANDC or ANDZ effect is specified, the C or Z flag is bitwise ANDed with the inverse state of the pin.

If the ORC or ORZ effect is specified, the C or Z flag is bitwise ORed with the inverse state of the pin.

If the XORC or XORZ effect is specified, the C or Z flag is bitwise XORed with the inverse state of the pin.

See also TESTP.

Smart Pin Instructions

{ SETQ {#}Q }
WRPIN {#}D,{#}S - Set pin mode

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1100000 0LI DDDDDDDDD SSSSSSSSS none --- --- 2 2 No

WRPIN sets the mode register of the pin(s) indicated by Source to the value in Destination.

TODO

{ SETQ {#}Q }
WXPIN {#}D,{#}S - Set smart pin X register

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1100000 1LI DDDDDDDDD SSSSSSSSS none --- --- 2 2 No

WXPIN sets the X register of the pin(s) indicated by Source to the value in Destination.

TODO

{ SETQ {#}Q }
WYPIN {#}D,{#}S - Set smart pin Y register

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1100001 0LI DDDDDDDDD SSSSSSSSS none --- --- 2 2 No

WYPIN sets the Y register of the pin(s) indicated by Source to the value in Destination.

TODO

RDPIN D,{#}S {WC} - Read smart pin Z register and acknowledge

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1010100 C1I DDDDDDDDD SSSSSSSSS D modal result --- 2 2 No

RQPIN D,{#}S {WC} - Read smart pin Z register and don't acknowledge

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1010100 C0I DDDDDDDDD SSSSSSSSS D modal result --- 2 2 No

RQPIN reads the value of the Z register of the pin indicated by Source into Destination and sends the pin an acknowledge signal.

RDPIN does the same but additionally sends an acknowledge signal to the pin.

{ SETQ {#}Q }
AKPIN {#}S - Acknowledge smart pin

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1100000 01I 000000001 SSSSSSSSS none --- --- 2 2 No

AKPIN is an alias for WRPIN #1,{#}S TODO

Other Instructions

SETDACS {#}D - Set DAC channel values

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 00L DDDDDDDDD 000011100 none --- --- 2 2 No

SETDACS sets the default values for the cog's four DAC channels (TODO link) to the four bytes of the Destination value. These values are used when the Streamer is not active.

SETSCP {#}D - Setup scope pipe

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 00L DDDDDDDDD 001110000 none --- --- 2 2 No

SETSCP configures the cog's scope data pipe. If Destination[6] is set, the scope data pipe is enabled and Destination[5:2] selects the group of 4 pins to capture from. The bottom two bits are ignored, so the group must be 4-aligned.

GETSCP D - Get scope pipe data

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 000 DDDDDDDDD 001110001 none --- --- 2 2 No

GETSCP reads the current state of the SCOPE data pipe into Destination.

GETSCP x is roughly equivalent to this sequence, where pinblock is the pin group set with SETSCP:

        RQPIN   tmp,#pinblock | 3     'read pin3 long into x
        ROLBYTE x,tmp,#0              'rotate pin3 byte into y
        RQPIN   tmp,#pinblock | 2     'read pin2 long into x
        ROLBYTE x,tmp,#0              'rotate pin2 byte into y
        RQPIN   tmp,#pinblock | 1     'read pin1 long into x
        ROLBYTE x,tmp,#0              'rotate pin1 byte into y
        RQPIN   tmp,#pinblock | 0     'read pin0 long into x
        ROLBYTE x,tmp,#0              'rotate pin0 byte into y

Smart Pin modes

TODO all of these

P_NORMAL (%00000) - Dumb pin mode

Normal operation, without any smart pin functionality.

P_REPOSITORY (%00001) - Long repository

Turns the smart pin into a one-long storage space, where WXPIN writes the long and RDPIN / RQPIN can read the long. This Only available when not using pin DAC (TODO clarify) - Upon each WXPIN, IN is raised. - During reset (DIR=0), IN is low.

P_DAC_NOISE (%00001) - DAC Noise

P_DAC_DITHER_RND (%00010) - DAC 16-bit random dither

P_DAC_DITHER_PWM (%00011) - DAC 16-bit PWM dither

P_PULSE (%00100) - Pulse/cycle output

P_TRANSITION (%00101) - Transition output

P_NCO_FREQ (%00110) - NCO frequency output

P_NCO_DUTY (%00111) - NCO duty output

P_PWM_TRIANGLE (%01000) - PWM triangle output

P_PWM_SAWTOOTH (%01001) - PWM sawtooth output

P_PWM_SMPS (%01010) - PWM Switch-Mode Power Supply With Voltage/Current Feedback

P_QUADRATURE (%01011) - A-B quadrature encoder input

P_REG_UP (%01100) - Inc on A-rise when B-high

P_REG_UP_DOWN (%01101) - Inc on A-rise when B-high, dec on A-rise when B-low

P_COUNT_RISES (%01110) - Inc on A-rise, optionally dec on B-rise

P_COUNT_HIGHS (%01111) - Inc on A-high, optionally dec on B-high

P_STATE_TICKS (%10000) - For A-low and A-high states, count ticks

P_HIGH_TICKS (%10001) - For A-high states, count ticks

P_EVENTS_TICKS (%10010) - For X A-highs/rises/edges, count ticks / Timeout on X ticks of no A-high/rise/edge

This mode has 2 sub-modes, selected by bit 2 of the Y register.

When Y[2] == 0

When Y[2] == 1

TODO HW manual split this one, maybe merge again?

P_PERIODS_TICKS (%10011) - For X periods of A, count ticks

P_PERIODS_HIGHS (%10100) - For X periods of A, count highs

TODO

P_COUNTER_TICKS (%10101) - For periods of A in X+ ticks, count ticks

TODO

P_COUNTER_HIGHS (%10110) - For periods of A in X+ ticks, count highs

TODO

P_COUNTER_PERIODS (%10111) - For periods of A in X+ ticks, count periods

TODO

P_ADC (%11000) - ADC sample/filter/capture, internally clocked

P_ADC_EXT (%11001) - ADC sample/filter/capture, externally clocked

These modes facilitate sampling, SINC filtering, and raw capturing of ADC bitstream data.

For the internally-clocked mode, the A-input will be sampled on every clock and should be a pin configured for ADC operation (M[12:10] = %100). In the externally-clocked mode, the A-input will be sampled on each B-input rise, so that an external delta-sigma ADC may be employed.

WXPIN sets the mode to X[5:4] and the sample period to 2X[3:0]. Not all mode and period combinations are useful, or even functional:

  X[5:4] ->
Mode ->
%00
SINC2 Sampling
%01
SINC2 Filtering
%10
SINC3 Filtering
%11
Bitstream capture
X[3:0] Sample Period Sample Resolution Post-diff ENOB* Post-diff ENOB* (LSB = oldest bit)
%0000 1 clock impractical impractical impractical 1 new bit
%0001 2 clocks 2 bits impractical impractical 2 new bits
%0010 4 clocks 3 bits impractical impractical 4 new bits
%0011 8 clocks 4 bits 4 impractical 8 new bits
%0100 16 clocks 5 bits 5 8 16 new bits
%0101 32 clocks 6 bits 6 10 32 new bits
%0110 64 clocks 7 bits 7 12 overflow
%0111 128 clocks 8 bits 8 14 overflow
%1000 256 clocks 9 bits 9 16 overflow
%1001 512 clocks 10 bits 10 18 overflow
%1010 1024 clocks 11 bits 11 overflow overflow
%1011 2048 clocks 12 bits 12 overflow overflow
%1100 4096 clocks 13 bits 13 overflow overflow
%1101 8192 clocks 14 bits 14 overflow overflow
%1110 16384 clocks overflow overflow overflow overflow
%1111 32768 clocks overflow overflow overflow overflow

* ENOB = Effective Number of Bits, or the sample resolution.

For modes other than SINC2 Sampling (X[5:4] != %00), WYPIN may be used after WXPIN to override the initial period established by X[3:0] and replace it with the arbitrary value in Y[13:0]. For example, if you'd like to do SINC3 filtering with a period of 320 clocks, you could follow the WXPIN with a WYPIN #320,adcpin. The smart pin accumulators are 27 bits wide. This allows up to 227/3 (=512) clocks per decimation in SINC3 filtering mode and up to 227/2 (=11585) clocks in SINC2 filtering mode.

Upon completion of each sample period, the measurement is placed in Z, IN is raised, and a new measurement begins. RDPIN/RQPIN can then be used to retrieve the completed measurement.

P_ADC_SCOPE (%11010) - ADC scope with trigger

TODO

P_USB_PAIR (%11011) - USB pin pair

This mode requires that two adjacent pins be configured together to form a USB pair, whose OUTs will be overridden to control their output states. These pins must be an even/odd pair, having only the LSB of their pin numbers different. For example: pins 0 and 1, pins 2 and 3, and pins 4 and 5 can form USB pairs. They can be configured via WRPIN with identical D data of %1_11011_0. Using D data of %0_11011_0 will disable output drive and effectively create a USB 'sniffer'. A new WRPIN can be done to effect such a change without resetting the smart pin.

WXPIN is used on the lower pin to establish the specific USB mode and set the baud rate. D[15] must be 1 for 'host' or 0 for 'device'. D[14] must be 1 for 'full-speed' or 0 for 'low-speed'. D[13:0] sets the baud rate, which is a 16-bit fraction of the system clock, whose two MSBs must be 0, necessitating that the baud rate be less than 1/4th of the system clock frequency. For example, if the main clock is 80MHz and you want a 12MHz baud rate (full-speed), use 12,000,000 / 80,000,000 * $10000 = 9830, or $2666. To use this baud rate and select 'host' mode and 'full-speed', you could do 'WXPIN ##$E666,lowerpin'.

The upper (odd) pin is the DP pin. This pin's IN is raised whenever the output buffer empties, signalling that a new output byte can be written via WYPIN to the lower (even) pin. No WXPIN/WYPIN instructions are used for this pin.

The lower (even) pin is the DM pin. This pin's IN is raised whenever a change of status occurs in the receiver, at which point a RDPIN/RQPIN can be used on this pin to read the 16-bit status word. WXPIN is used on this pin to set the NCO baud rate.

These DP/DM electrical designations can actually be switched by swapping low-speed and full-speed modes, due to USB's complementary line signalling.

To start USB, clear the DIR bits of the intended two pins and configure them each via WRPIN. Use WXPIN on the lower pin to set the mode and baud rate. Then, set the pins' DIR bits. You are now ready to read the receiver status via RDPIN/RQPIN and set output states and send packets via WYPIN, both on the lower pin.

To affect the line states or send a packet, use WYPIN on the lower pin. Here are its D values:

    0 = output IDLE     - default state, float pins, except possible resistor(s) to 3.3V or GND
    1 = output SE0      - drive both DP and DM low
    2 = output K        - drive K state onto DP and DM (opposite)
    3 = output J        - drive J state onto DP and DM (opposite), like IDLE, but driven
    4 = output EOP      - output end-of-packet: SE0, SE0, J, then IDLE
    $80 = SOP           - output start-of-packet, then bytes, automatic EOP when buffer runs out

To send a packet, first do a WYPIN #$80,lowerpin. Then, after each IN rise on the upper pin, do a WYPIN byte,lowerpin to buffer the next byte. The transmitter will automatically send an EOP when you stop giving it bytes. To keep the output buffer from overflowing, you should always verify that the upper pin's IN was raised after each WYPIN, before issuing another WYPIN, even if you are just setting a state. The reason for this is that all output activity is timed to the baud generator and even state changes must wait for the next bit period before being implemented, at which time the output buffer empties.

There are separate state machines for transmitting and receiving. Only the baud generator is common between them. The transmitter was just described above. Below, the receiver is detailed. Note that the receiver receives not just input from another host/device, but all local output, as well.

At any time, a RDPIN/RQPIN can be executed on the lower pin to read the current 16-bit status of the receiver, with the error flag going into C. The lower pin's IN will be raised whenever a change occurs in the receiver's status. This will necessitate A WRPIN/WXPIN/WYPIN/RDPIN/AKPIN before IN can be raised again, to alert of the next change in status. The receiver's status bits are as follows:

    [31:16] <unused>            - $0000
    [15:8]  byte                - last byte received
    [7]     byte toggle         - cleared on SOP, toggled on each byte received
    [6]     error               - cleared on SOP, set on bit-unstuff error, EOP SE0 > 3 bits, or SE1
    [5]     EOP in              - cleared on SOP or 7+ bits of J or K, set on EOP
    [4]     SOP in              - cleared on EOP or 7+ bits of J or K, set on SOP
    [3]     SE1 in  (illegal)   - cleared on !SE1, set on 1+ bits of SE1
    [2]     SE0 in  (RESET)     - cleared on !SE0, set on 1+ bits of SE0
    [1]     K in    (RESUME)    - cleared on !K, set on 7+ bits of K
    [0]     J in    (IDLE)      - cleared on !J, set on 7+ bits of J

The result of a RDPIN/RQPIN can be bit-tested for events of interest. It can also be shifted right by 8 bits to LSB-justify the last byte received and get the byte toggle bit into C, in order to determine if you have a new byte. Assume that 'flag' is initially zero:

       SHR     D,#8    WC      'get byte into D, get toggle bit into C
       CMPX    flag,#1 WZ      'compare toggle bit to flag, new byte if Z
IF_Z   XOR     flag,#1         'if new byte, toggle flag
IF_Z   <use byte>              'if new byte, do something with it

P_SYNC_TX (%11100) - Synchronous serial transmit

This mode overrides OUT to control the pin output state.

Words of 1 to 32 bits are shifted out on the pin, LSB first, with each new bit being output two internal clock cycles after registering a positive edge on the B input. For negative-edge clocking, the B input may be inverted by setting B[3] in WRPIN's D value (TODO what???).

WXPIN is used to configure the update mode and word length.

X[5] selects the update mode:

X[5] = 0 sets continuous mode, where a first word is written via WYPIN during reset (DIR=0) to prime the shifter. Then, after reset (DIR=1), the second word is buffered via WYPIN and continuous clocking is started. Upon shifting each word, the buffered data written via WYPIN is advanced into the shifter and IN is raised, indicating that a new output word can be buffered via WYPIN. This mode allows steady data transmission with a continuous clock, as long as the WYPIN's after each IN-rise occur before the current word transmission is complete.

X[5] = 1 sets start-stop mode, where the current output word can always be updated via WYPIN before the first clock, flowing right through the buffer into the shifter. Any WYPIN issued after the first clock will be buffered and loaded into the shifter after the last clock of the current output word, at which time it could be changed again via WYPIN. This mode is useful for setting up the output word before a stream of clocks are issued to shift it out.

X[4:0] sets the number of bits, minus 1. For example, a value of 7 will set the word size to 8 bits.

WYPIN is used to load the output words. The words first go into a single-stage buffer before being advanced to the shifter for output. Each time the buffer is advanced into the shifter, IN is raised, indicating that a new output word can be written via WYPIN. During reset, the buffer flows straight into the shifter.

If you intend to send MSB-first data, you must first shift and then reverse it. For example, if you had a byte in D that you wanted to send MSB-first, you would do a SHL D,#32-8 and then a REV D.

During reset (DIR=0) the output is held low. Upon release of reset, the output will reflect the LSB of the output word written by any WYPIN during reset.

P_SYNC_RX (%11101) - Synchronous serial receive

Words of 1 to 32 bits are shifted in by sampling the A input around the positive edge of the B input. For negative-edge clocking, the B input may be inverted by setting B[3] in WRPIN's D value (TODO what???).

WXPIN is used to configure the sampling and word length.

X[5] selects the A input sample position relative to the B input edge:

X[5] = 0 selects the A input sample just before the B input edge was registered. This requires no hold time on the part of the sender.

X[5] = 1 selects the sample coincident with the B edge being registered. This is useful where transmitted data remains steady after the B edge for a brief time. In the synchronous serial transmit mode, the data is steady for two internal clocks after the B edge was registered, so employing this complementary feature would enable the fastest data transmission when receiving from another smart pin in synchronous serial transmit mode.

X[4:0] sets the number of bits, minus 1. For example, a value of 7 will set the word size to 8 bits.

When a word is received, IN is raised and the data can then be read via RDPIN/RQPIN. The data read will be MSB-justified.

If you received LSB-first data, it will require right-shifting, unless the word size was 32 bits. For a word size of 8 bits, you would need to do a 'SHR D,#32-8' to get the data LSB-justified.

If you received MSB-first data, it will need to be reversed and possibly masked, unless the word size was 32 bits. For example, if you received a 9-bit word, you would do REV D + ZEROX D,#8 to get the data LSB-justified.

P_ASYNC_TX (%11110) - Asynchronous serial transmit

This mode overrides OUT to control the pin output state.

Words from 1 to 32 bits are serially transmitted on the pin at a programmable baud rate, beginning with a low "start" bit and ending with a high "stop" bit.

WXPIN is used to configure the baud rate and word length.

X[31:16] establishes the number of clocks in a bit period, and in case X[31:26] is zero, X[15:10] establishes the number of fractional clocks in a bit period. The X bit period value can be simply computed as: (clocks * $1_0000) & $FFFFFC00. For example, 7.5 clocks would be $00078000, and 33.33 clocks would be $00215400.

X[4:0] sets the number of bits, minus 1. For example, a value of 7 will set the word size to 8 bits.

WYPIN is used to load the output words. The words first go into a single-stage buffer before being advanced to a shifter for output. This buffering mechanism makes it possible to keep the shifter constantly busy, so that gapless transmissions can be achieved. Any time a word is advanced from the buffer to the shifter, IN is raised, indicating that a new word can be loaded. IN is not raised on startup/reset.

Here is the internal state sequence:

  1. Wait for an output word to be buffered via WYPIN, then set the 'buffer-full' and 'busy' flags.
  2. Move the word into the shifter, clear the 'buffer-full' flag, and raise IN.
  3. Output a low for one bit period (the START bit).
  4. Output the LSB of the shifter for one bit period, shift right, and repeat until all data bits are sent.
  5. Output a high for one bit period (the STOP bit).
  6. If the 'buffer-full' flag is set due to an intervening WYPIN, loop to (2). Otherwise, clear the 'busy' flag and loop to (1).

RDPIN/RQPIN with WC always returns the 'busy' flag into C. This is useful for knowing when a transmission has completed. The busy flag can be polled starting three clocks after the WYPIN, which loads the output words:

       WYPIN   x,#txpin        'load output word
       WAITX   #1              'wait 2+1 clocks before polling busy
wait   RDPIN   x,#txpin  WC    'get busy flag into C
IF_C   JMP     #wait           'loop until C = 0

During reset (DIR=0) the output is held high.

P_ASYNC_RX (%11111) - Asynchronous serial receive

Words from 1 to 32 bits are serially received on the A input at a programmable baud rate.

WXPIN is used to configure the baud rate and word length.

X[31:16] establishes the number of clocks in a bit period, and in case X[31:26] is zero, X[15:10] establishes the number of fractional clocks in a bit period. The X bit period value can be simply computed as: (clocks * $1_0000) & $FFFFFC00. For example, 7.5 clocks would be $00078000, and 33.33 clocks would be $00215400.

X[4:0] sets the number of bits, minus 1. For example, a value of 7 will set the word size to 8 bits.

Here is the internal state sequence:

  1. Wait for the A input to go high (idle state).
  2. Wait for the A input to go low (START bit edge).
  3. Delay for half of a bit period.
  4. If the A input is no longer low, loop to (2).
  5. Delay for one bit period.
  6. Right-shift the A input into the shifter and delay for one bit period, repeat until all data bits are received.
  7. Capture the shifter into the Z register and raise IN.
  8. Loop to (1).

RDPIN/RQPIN is used to read the received word. The word must be shifted right by 32 minus the word size. For example, to LSB-justify an 8-bit word received, you would do a SHR D,#32-8.