// File: lucaong[P]elixir_mlx90640/src/main.cpp
// Function: main
int main(int argc, char *argv[]) {
  static uint16_t eeMLX90640[832];
  float emissivity = 1;
  uint16_t frame[834];
  static float mlx90640To[PIXELS];
  float eTa;
  int fps = 2;

  if (argc > 1) {
    fps = atoi(argv[1]);
  }

  MLX90640_SetControlRegister(MLX_I2C_ADDR, 0b0001101000000001);

  if (fps == 1) {
    MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b001);
  } else if (fps == 2) {
    MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b010);
  } else if (fps == 4) {
    MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b011);
  } else if (fps == 8) {
    MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b100);
  } else if (fps == 16) {
    MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b101);
  } else if (fps == 32) {
    MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b110);
  } else if (fps == 64) {
    MLX90640_SetRefreshRate(MLX_I2C_ADDR, 0b111);
  } else {
    err(EXIT_FAILURE, "%s: %d", "Unsupported framerate", fps);
    return 1;
  }
  
  auto frame_time = std::chrono::microseconds(1000000 / fps + OFFSET_MICROS);

  MLX90640_SetChessMode(MLX_I2C_ADDR);

  paramsMLX90640 mlx90640;
  MLX90640_DumpEE(MLX_I2C_ADDR, eeMLX90640);
  MLX90640_ExtractParameters(eeMLX90640, &mlx90640);

  while (1) {
    auto start = std::chrono::system_clock::now();
    MLX90640_GetFrameData(MLX_I2C_ADDR, frame);

    eTa = MLX90640_GetTa(frame, &mlx90640);
    MLX90640_CalculateTo(frame, &mlx90640, emissivity, eTa, mlx90640To);

    output_measurement(mlx90640To);

    auto end = std::chrono::system_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::this_thread::sleep_for(std::chrono::microseconds(frame_time - elapsed));
  }

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3150, %rsp           # imm = 0x3150
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movss 0x4b3f(%rip), %xmm0     # 0x6010
movss %xmm0, -0x14(%rbp)
movl $0x2, -0x6a8(%rbp)
cmpl $0x1, -0x8(%rbp)
jle 0x14f9
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x1100
movl %eax, -0x6a8(%rbp)
movl $0x33, %edi
movl $0x1a01, %esi           # imm = 0x1A01
callq 0x5a20
cmpl $0x1, -0x6a8(%rbp)
jne 0x1525
movl $0x33, %edi
movl $0x1, %esi
callq 0x3b80
jmp 0x15f3
cmpl $0x2, -0x6a8(%rbp)
jne 0x1542
movl $0x33, %edi
movl $0x2, %esi
callq 0x3b80
jmp 0x15f1
cmpl $0x4, -0x6a8(%rbp)
jne 0x155f
movl $0x33, %edi
movl $0x3, %esi
callq 0x3b80
jmp 0x15ef
cmpl $0x8, -0x6a8(%rbp)
jne 0x1579
movl $0x33, %edi
movl $0x4, %esi
callq 0x3b80
jmp 0x15ed
cmpl $0x10, -0x6a8(%rbp)
jne 0x1593
movl $0x33, %edi
movl $0x5, %esi
callq 0x3b80
jmp 0x15eb
cmpl $0x20, -0x6a8(%rbp)
jne 0x15ad
movl $0x33, %edi
movl $0x6, %esi
callq 0x3b80
jmp 0x15e9
cmpl $0x40, -0x6a8(%rbp)
jne 0x15c7
movl $0x33, %edi
movl $0x7, %esi
callq 0x3b80
jmp 0x15e7
movl -0x6a8(%rbp), %ecx
movl $0x1, %edi
leaq 0x4a3b(%rip), %rsi      # 0x6014
leaq 0x4a48(%rip), %rdx      # 0x6028
movb $0x0, %al
callq 0x10d0
jmp 0x15e9
jmp 0x15eb
jmp 0x15ed
jmp 0x15ef
jmp 0x15f1
jmp 0x15f3
movl $0xf4240, %eax          # imm = 0xF4240
cltd
idivl -0x6a8(%rbp)
addl $0x352, %eax            # imm = 0x352
movl %eax, -0x6b4(%rbp)
leaq -0x6b0(%rbp), %rdi
leaq -0x6b4(%rbp), %rsi
callq 0x1720
movl $0x33, %edi
callq 0x3cc0
movl $0x33, %edi
leaq 0x7abd(%rip), %rsi      # 0x90f0
callq 0x1d60
leaq 0x7ab1(%rip), %rdi      # 0x90f0
leaq -0x3124(%rbp), %rsi
callq 0x1f50
callq 0x1050
movq %rax, -0x3130(%rbp)
leaq -0x6a0(%rbp), %rsi
movl $0x33, %edi
callq 0x1da0
leaq -0x6a0(%rbp), %rdi
leaq -0x3124(%rbp), %rsi
callq 0x4810
movss %xmm0, -0x6a4(%rbp)
leaq -0x6a0(%rbp), %rdi
movss -0x14(%rbp), %xmm0
movss -0x6a4(%rbp), %xmm1
leaq -0x3124(%rbp), %rsi
leaq 0x80cb(%rip), %rdx      # 0x9770
callq 0x3d80
leaq 0x80bf(%rip), %rdi      # 0x9770
callq 0x1420
callq 0x1050
movq %rax, -0x3138(%rbp)
leaq -0x3138(%rbp), %rdi
leaq -0x3130(%rbp), %rsi
callq 0x1770
movq %rax, -0x3148(%rbp)
leaq -0x3148(%rbp), %rdi
callq 0x1740
movq %rax, -0x3140(%rbp)
leaq -0x6b0(%rbp), %rdi
leaq -0x3140(%rbp), %rsi
callq 0x1870
movq %rax, -0x3150(%rbp)
leaq -0x3150(%rbp), %rdi
callq 0x17c0
jmp 0x164b
nopw (%rax,%rax)