// File: eggnot[P]pixel_camera/matrix/lib/framebuffer.cc
// Function: rgb_matrix::internal::Framebuffer::DumpToMatrix(rgb_matrix::GPIO*)
void Framebuffer::DumpToMatrix(GPIO *io) {
  IoBits color_clk_mask;   // Mask of bits we need to set while clocking in.
  color_clk_mask.bits.p0_r1
    = color_clk_mask.bits.p0_g1
    = color_clk_mask.bits.p0_b1
    = color_clk_mask.bits.p0_r2
    = color_clk_mask.bits.p0_g2
    = color_clk_mask.bits.p0_b2 = 1;

#ifndef ONLY_SINGLE_CHAIN
  if (parallel_ >= 2) {
    color_clk_mask.bits.p1_r1
      = color_clk_mask.bits.p1_g1
      = color_clk_mask.bits.p1_b1
      = color_clk_mask.bits.p1_r2
      = color_clk_mask.bits.p1_g2
      = color_clk_mask.bits.p1_b2 = 1;
  }

  if (parallel_ >= 3) {
    color_clk_mask.bits.p2_r1
      = color_clk_mask.bits.p2_g1
      = color_clk_mask.bits.p2_b1
      = color_clk_mask.bits.p2_r2
      = color_clk_mask.bits.p2_g2
      = color_clk_mask.bits.p2_b2 = 1;
  }
#endif

#ifdef PI_REV1_RGB_PINOUT_
  color_clk_mask.bits.clock_rev1 = color_clk_mask.bits.clock_rev2 = 1;
#endif
  color_clk_mask.bits.clock = 1;

  IoBits row_mask;
  row_mask.bits.a = row_mask.bits.b = row_mask.bits.c = row_mask.bits.d = 1;

  IoBits clock, strobe, row_address;
#ifdef PI_REV1_RGB_PINOUT_
  clock.bits.clock_rev1 = clock.bits.clock_rev2 = 1;
#endif
  clock.bits.clock = 1;
  strobe.bits.strobe = 1;

  const int pwm_to_show = pwm_bits_;  // Local copy, might change in process.
  for (uint8_t d_row = 0; d_row < double_rows_; ++d_row) {
    row_address.bits.a = d_row;
    row_address.bits.b = d_row >> 1;
    row_address.bits.c = d_row >> 2;
    row_address.bits.d = d_row >> 3;

    io->WriteMaskedBits(row_address.raw, row_mask.raw);  // Set row address

    // Rows can't be switched very quickly without ghosting, so we do the
    // full PWM of one row before switching rows.
    for (int b = kBitPlanes - pwm_to_show; b < kBitPlanes; ++b) {
      IoBits *row_data = ValueAt(d_row, 0, b);
      // While the output enable is still on, we can already clock in the next
      // data.
      for (int col = 0; col < columns_; ++col) {
        const IoBits &out = *row_data++;
        io->WriteMaskedBits(out.raw, color_clk_mask.raw);  // col + reset clock
        io->SetBits(clock.raw);               // Rising edge: clock color in.
      }
      io->ClearBits(color_clk_mask.raw);    // clock back to normal.

      // OE of the previous row-data must be finished before strobe.
      sOutputEnablePulser->WaitPulseFinished();

      io->SetBits(strobe.raw);   // Strobe in the previously clocked in row.
      io->ClearBits(strobe.raw);

      // Now switch on for the sleep time necessary for that bit-plane.
      sOutputEnablePulser->SendPulse(b);
    }
    sOutputEnablePulser->WaitPulseFinished();
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x50(%rbp)
leaq -0x14(%rbp), %rdi
callq 0x80f0
movq -0x50(%rbp), %rax
movl -0x14(%rbp), %ecx
andl $0xfffffbff, %ecx       # imm = 0xFFFFFBFF
orl $0x400, %ecx            # imm = 0x400
movl %ecx, -0x14(%rbp)
movl -0x14(%rbp), %ecx
andl $0xfffffdff, %ecx       # imm = 0xFFFFFDFF
orl $0x200, %ecx            # imm = 0x200
movl %ecx, -0x14(%rbp)
movl -0x14(%rbp), %ecx
andl $0xfffffeff, %ecx       # imm = 0xFFFFFEFF
orl $0x100, %ecx            # imm = 0x100
movl %ecx, -0x14(%rbp)
movl -0x14(%rbp), %ecx
andl $0xffffff7f, %ecx       # imm = 0xFFFFFF7F
orl $0x80, %ecx
movl %ecx, -0x14(%rbp)
movl -0x14(%rbp), %ecx
andl $0xf7ffffff, %ecx       # imm = 0xF7FFFFFF
orl $0x8000000, %ecx        # imm = 0x8000000
movl %ecx, -0x14(%rbp)
movl -0x14(%rbp), %ecx
andl $0xfffff7ff, %ecx       # imm = 0xFFFFF7FF
orl $0x800, %ecx            # imm = 0x800
movl %ecx, -0x14(%rbp)
cmpl $0x2, 0x4(%rax)
jl 0x7d2f
movl -0x14(%rbp), %eax
andl $0xffefffff, %eax       # imm = 0xFFEFFFFF
orl $0x100000, %eax         # imm = 0x100000
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xffffdfff, %eax       # imm = 0xFFFFDFFF
orl $0x2000, %eax           # imm = 0x2000
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xfff7ffff, %eax       # imm = 0xFFF7FFFF
orl $0x80000, %eax          # imm = 0x80000
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $-0x41, %eax
orl $0x40, %eax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $-0x21, %eax
orl $0x20, %eax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xffffefff, %eax       # imm = 0xFFFFEFFF
orl $0x1000, %eax           # imm = 0x1000
movl %eax, -0x14(%rbp)
movq -0x50(%rbp), %rax
cmpl $0x3, 0x4(%rax)
jl 0x7d91
movl -0x14(%rbp), %eax
andl $0xffdfffff, %eax       # imm = 0xFFDFFFFF
orl $0x200000, %eax         # imm = 0x200000
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xfffeffff, %eax       # imm = 0xFFFEFFFF
orl $0x10000, %eax          # imm = 0x10000
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xfbffffff, %eax       # imm = 0xFBFFFFFF
orl $0x4000000, %eax        # imm = 0x4000000
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $-0x9, %eax
orl $0x8, %eax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $-0x5, %eax
orl $0x4, %eax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xffffbfff, %eax       # imm = 0xFFFFBFFF
orl $0x4000, %eax           # imm = 0x4000
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xfffdffff, %eax       # imm = 0xFFFDFFFF
orl $0x20000, %eax          # imm = 0x20000
movl %eax, -0x14(%rbp)
leaq -0x18(%rbp), %rdi
callq 0x80f0
movl -0x18(%rbp), %eax
andl $0xfdffffff, %eax       # imm = 0xFDFFFFFF
orl $0x2000000, %eax        # imm = 0x2000000
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
andl $0xfeffffff, %eax       # imm = 0xFEFFFFFF
orl $0x1000000, %eax        # imm = 0x1000000
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
andl $0xff7fffff, %eax       # imm = 0xFF7FFFFF
orl $0x800000, %eax         # imm = 0x800000
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
andl $0xffbfffff, %eax       # imm = 0xFFBFFFFF
orl $0x400000, %eax         # imm = 0x400000
movl %eax, -0x18(%rbp)
leaq -0x1c(%rbp), %rdi
callq 0x80f0
leaq -0x20(%rbp), %rdi
callq 0x80f0
leaq -0x24(%rbp), %rdi
callq 0x80f0
movq -0x50(%rbp), %rax
movl -0x1c(%rbp), %ecx
andl $0xfffdffff, %ecx       # imm = 0xFFFDFFFF
orl $0x20000, %ecx          # imm = 0x20000
movl %ecx, -0x1c(%rbp)
movl -0x20(%rbp), %ecx
andl $-0x11, %ecx
orl $0x10, %ecx
movl %ecx, -0x20(%rbp)
movzbl 0x10(%rax), %eax
movl %eax, -0x28(%rbp)
movb $0x0, -0x29(%rbp)
movq -0x50(%rbp), %rcx
movzbl -0x29(%rbp), %eax
cmpl 0x14(%rcx), %eax
jge 0x7f99
movzbl -0x29(%rbp), %ecx
movl -0x24(%rbp), %eax
andl $0x1, %ecx
shll $0x16, %ecx
andl $0xffbfffff, %eax       # imm = 0xFFBFFFFF
orl %ecx, %eax
movl %eax, -0x24(%rbp)
movzbl -0x29(%rbp), %ecx
sarl %ecx
movl -0x24(%rbp), %eax
andl $0x1, %ecx
shll $0x17, %ecx
andl $0xff7fffff, %eax       # imm = 0xFF7FFFFF
orl %ecx, %eax
movl %eax, -0x24(%rbp)
movzbl -0x29(%rbp), %ecx
sarl $0x2, %ecx
movl -0x24(%rbp), %eax
andl $0x1, %ecx
shll $0x18, %ecx
andl $0xfeffffff, %eax       # imm = 0xFEFFFFFF
orl %ecx, %eax
movl %eax, -0x24(%rbp)
movzbl -0x29(%rbp), %ecx
sarl $0x3, %ecx
movl -0x24(%rbp), %eax
andl $0x1, %ecx
shll $0x19, %ecx
andl $0xfdffffff, %eax       # imm = 0xFDFFFFFF
orl %ecx, %eax
movl %eax, -0x24(%rbp)
movq -0x10(%rbp), %rdi
movl -0x24(%rbp), %esi
movl -0x18(%rbp), %edx
callq 0x8230
movl $0xb, %eax
subl -0x28(%rbp), %eax
movl %eax, -0x30(%rbp)
cmpl $0xb, -0x30(%rbp)
jge 0x7f7f
movq -0x50(%rbp), %rdi
movzbl -0x29(%rbp), %esi
movl -0x30(%rbp), %ecx
xorl %edx, %edx
callq 0x81f0
movq %rax, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
movq -0x50(%rbp), %rcx
movl -0x3c(%rbp), %eax
cmpl 0xc(%rcx), %eax
jge 0x7f30
movq -0x38(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x38(%rbp)
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
movq -0x48(%rbp), %rax
movl (%rax), %esi
movl -0x14(%rbp), %edx
callq 0x8230
movq -0x10(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x5180
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x7ee8
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x5150
movq 0x6285(%rip), %rdi      # 0xe1c8
movq (%rdi), %rax
callq *0x18(%rax)
movq -0x10(%rbp), %rdi
movl -0x20(%rbp), %esi
callq 0x5180
movq -0x10(%rbp), %rdi
movl -0x20(%rbp), %esi
callq 0x5150
movq 0x6260(%rip), %rdi      # 0xe1c8
movl -0x30(%rbp), %esi
movq (%rdi), %rax
callq *0x10(%rax)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x7ec1
movq 0x6242(%rip), %rdi      # 0xe1c8
movq (%rdi), %rax
callq *0x18(%rax)
movb -0x29(%rbp), %al
addb $0x1, %al
movb %al, -0x29(%rbp)
jmp 0x7e32
addq $0x50, %rsp
popq %rbp
retq
nop