section text

// 等待第一个下降沿
L0:
    xor r3, r3              // 00 | 10111111
    not r3                  // 01 | 10100011
    in r0                   // 02 | 01010000
    // 下降沿后， and 指令会设置一个零标志
    and r0, r3              // 03 | 10000011

    // 零标志时跳转至 recv_pre
    mov recv_pre, r0        // 04 | 00100000
                            // 05 | 00001000 : recv_pre
    jz r0                   // 06 | 01001000

    // 不跳转回到开头继续等待
    rtn                     // 07 | 01110000

// 第一个下降沿后，计算采样点的计数（当前计数+108）          // 可直接存储立即数
recv_pre:                   // 08
    // r3=108
    mov 5, r0               // 08 | 00100000
                            // 09 | 00000101
    mov 3, r3               // 0a | 00100011
                            // 0b | 00000011
    shl r0, r3              // 0c | 11000011
    mov 0xc, r0             // 0d | 00100000
                            // 0e | 00001100
    add r0, r3              // 0f | 11010011

    // r1 = ucnt - 108
    mov ucnt, r0            // 10 | 00100000
                            // 11 | 00000111 : ucnt

    mov (r0), r1            // 12 | 01100001
    sub r3, r1              // 13 | 11111101

    // if (r1 < 0) r1 = r1 + 216                         // 可直接使用 jc 判断
    mov 7, r2               // 14 | 00100010
                            // 15 | 00000111
    mov 1, r0               // 16 | 00100000
                            // 17 | 00000001
    shl r2, r0              // 18 | 11001000
    and r0, r1              // 19 | 10000001
    mov 1f, r0              // 1a | 00100000
                            // 1b | 00100001 : 1f
    jz r0                   // 1c | 01001000
    mov 1, r0               // 1d | 00100000
                            // 1e | 00000001
    // r3 << 1 (r3 = 216)
    shl r0, r3              // 1f | 11000011
    add r3, r1              // 20 | 11011101
    1:                      // 21

    // (testpoint) = r1
    mov testpoint, r0       // 21 | 00100000
                            // 22 | 00000110 : testpoint
    mov r1, (r0)            // 23 | 00010100
    // (attp) = 0
    xor r1, r1              // 24 | 10110101
    mov attp, r0            // 25 | 00100000
                            // 26 | 00000101 : attp
    mov r1, (r0)            // 27 | 00010100

    // 8个采样周期，作为循环计数
    // (recv_bcnt) = 8
    mov 8, r1               // 28 | 00100001
                            // 29 | 00001000
    mov recv_bcnt, r0       // 2a | 00100000
                            // 2b | 00000000 : recv_bcnt
    mov r1, (r0)            // 2c | 00010100

// 1.5个周期后是第一个采样点，所以先跳过一个采样点
// 因为指令读取 attp 的行为对于时钟计数有延迟，
// 实际上有很小的概率把第一个采样点跳过，导致数据错误
L2:                         // 2d
    mov attp, r0            // 2d | 00100000
                            // 2e | 00000101 : attp
    mov (r0), r1            // 2f | 01100001
    mov 1, r0               // 30 | 00100000
                            // 31 | 00000001
    and r0, r1              // 32 | 10000001
    mov L2, r0              // 33 | 00100000
                            // 34 | 00101101 : L2
    jz r0                   // 35 | 01001000

    xor r1, r1              // 36 | 10110101
    mov attp, r0            // 37 | 00100000
                            // 38 | 00000101
    mov r1, (r0)            // 39 | 00010100

recv:                       // 3a
    // attp 在 ucnt 到达 testpoint 时会自动设为1
    // 检测 attp 即可得知是否到达当前采样点
    mov attp, r0            // 3a | 00100000
                            // 3b | 00000101 : attp
    mov (r0), r1            // 3c | 01100001
    mov 1, r0               // 3d | 00100000
                            // 3e | 00000001
    and r0, r1              // 3f | 10000001
    // 没到采样点时跳转回recv
    mov recv, r0            // 40 | 00100000
                            // 41 | 00111010 : recv
    jz r0                   // 42 | 01001000

    // 否则开始采样，先右移将上次采样结果保留
    // 再使用 in 指令将这次的接收线的值存下来
    mov 1, r0               // 43 | 00100000
                            // 44 | 00000001
    shr r0, r3              // 45 | 11100011
    in r3                   // 46 | 01010011

    // 将 attp 置 0，以等待下次的采样点到达
    xor r1, r1              // 47 | 10110101
    mov attp, r0            // 48 | 00100000
                            // 49 | 00000101 : attp
    mov r1, (r0)            // 4a | 00010100

    // 循环计数减1
    mov recv_bcnt, r0       // 4b | 00100000
                            // 4c | 00000000 : recv_bcnt
    mov (r0), r1            // 4d | 01100001
    mov 1, r0               // 4e | 00100000
                            // 4f | 00000001
    sub r0, r1              // 50 | 11110001
    mov recv_bcnt, r0       // 51 | 00100000
                            // 52 | 00000000 : recv_bcnt
    mov r1, (r0)            // 53 | 00010100
    mov 0xff, r0            // 54 | 00100000
                            // 55 | 11111111
    and r0, r1              // 56 | 10000001

    // 循环计数为0时进入发送阶段
    mov send_pre, r0        // 57 | 00100000
                            // 58 | 01011101 : send_pre
    jz r0                   // 59 | 01001000

    // 否则跳回recv
    mov recv, r0            // 5a | 00100000
                            // 5b | 00111010 : recv
    jmp r0                  // 5c | 01000000

// 发送准备阶段
send_pre:                   // 5d
    xor r1, r1              // 5d | 10110101

    // 因为是发送，采样点简单设为0就行，不需要特殊计算
    mov testpoint, r0       // 5e | 00100000
                            // 5f | 00000110 : testpoint
    mov r1, (r0)            // 60 | 00010100

    mov attp, r0            // 61 | 00100000
                            // 62 | 00000101 : attp
    mov r1, (r0)            // 63 | 00010100

    // 8个采样周期，作为循环计数，这里懒得改符号名了，所以还是 recv_bcnt
    // (recv_bcnt) = 8
    mov 8, r1               // 64 | 00100001
                            // 65 | 00001000
    mov recv_bcnt, r0       // 66 | 00100000
                            // 67 | 00000000 : recv_bcnt
    mov r1, (r0)            // 68 | 00010100

// 加载起始位
L1:                         // 69
    mov attp, r0            // 69 | 00100000
                            // 6a | 00000101 : attp
    mov (r0), r1            // 6b | 01100001
    mov 1, r0               // 6c | 00100000
                            // 6d | 00000001
    and r0, r1              // 6e | 10000001
    mov L1, r0              // 6f | 00100000
                            // 70 | 01101001 : L1
    jz r0                   // 71 | 01001000

    // r0 归零，并输出 r0
    xor r0, r0              // 72 | 10110000
    out r0                  // 73 | 01010100

    // 将 attp 置 0，以等待下次的采样点到达
    xor r1, r1              // 74 | 10110101
    mov attp, r0            // 75 | 00100000
                            // 76 | 00000101 : attp
    mov r1, (r0)            // 77 | 00010100

// 发送8个数据位
send:                       // 78
    mov attp, r0            // 78 | 00100000
                            // 79 | 00000101 : attp
    mov (r0), r1            // 7a | 01100001
    mov 1, r0               // 7b | 00100000
                            // 7c | 00000001
    and r0, r1              // 7d | 10000001

    // 没到采样点时跳回 send
    mov send, r0            // 7e | 00100000
                            // 7f | 01111000 : send
    jz r0                   // 80 | 01001000

    // 先输出 r3 ，再将 r3 右移，这样下次再执行到这里时，输出的最低位依然是要发送的位
    out r3                  // 81 | 01010111
    mov 1, r0               // 82 | 00100000
                            // 83 | 00000001
    shr r0, r3              // 84 | 11100011

    // attp 置 0，不再重复说明
    xor r1, r1              // 85 | 10110101
    mov attp, r0            // 86 | 00100000
                            // 87 | 00000101 : attp
    mov r1, (r0)            // 88 | 00010100

    // 循环计数减1
    mov recv_bcnt, r0       // 89 | 00100000
                            // 8a | 00000000 : recv_bcnt
    mov (r0), r1            // 8b | 01100001
    mov 1, r0               // 8c | 00100000
                            // 8d | 00000001
    sub r0, r1              // 8e | 11110001
    mov recv_bcnt, r0       // 8f | 00100000
                            // 90 | 00000000 : recv_bcnt
    mov r1, (r0)            // 91 | 00010100
    mov 0xf, r0             // 92 | 00100000
                            // 93 | 00001111
    and r0, r1              // 94 | 10000001

    // 循环计数为0时发送完成，即将发送结束位
    mov tr_end, r0          // 95 | 00100000
                            // 96 | 10011011 : tr_end
    jz r0                   // 97 | 01001000

    // 否则回到 send，发送下一位
    mov send, r0            // 98 | 00100000
                            // 99 | 01111000 : send
    jmp r0                  // 9a | 01000000

// 传输完成，发送结束位
tr_end:                     // 9b
    mov attp, r0            // 9b | 00100000
                            // 9c | 00000101 : attp
    mov (r0), r1            // 9d | 01100001
    mov 1, r0               // 9e | 00100000
                            // 9f | 00000001
    and r0, r1              // a0 | 10000001

    // 同样读取 attp ，没到采样点时跳回 tr_end
    mov tr_end, r0          // a1 | 00100000
                            // a2 | 10011011 : tr_end
    jz r0                   // a3 | 01001000

    // 加载结束位
    mov 1, r0               // a4 | 00100000
                            // a5 | 00000001
    out r0                  // a6 | 01010100

    // 回到开头接收下一个字节
    rtn                     // a7 | 01110000

section data

recv_bcnt: 8

preserved: resb 5 - .

attp: 0
testpoint: 0
ucnt:
