// File: SYZYGYfpga[P]brain-tools/src/sequencer-brain.cpp
// Function: main
int main (int argc, char *argv[])
{
	// Options flags
	int hflag = 0;
	int wflag = 0;
	int dflag = 0;
	char i2c_filename[200];
	char seq_filename[200];
	uint8_t seq_buf[9];
	int i2c_file;
	int seq_file;
	int periph_num = 0;
	int curr_opt;
	int err;
	json json_handler;
	uint16_t peripheral_address[] = {0x30, 0x31, 0x32, 0x33};

	// Parse args
	while ((curr_opt = getopt(argc, argv, "w:d:p:h")) != -1) {
		switch(curr_opt)
		{
			case 'w':
				wflag = 1;
				if (optarg){ 
					strcpy(seq_filename, optarg);
				} else {
					printf("No argument specified for -w\n");
					exit(EXIT_FAILURE);
				}
				break;
			case 'd':
				dflag = 1;
				if (optarg){ 
					strcpy(seq_filename, optarg);
				} else {
					printf("No argument specified for -d\n");
					exit(EXIT_FAILURE);
				}
				break;
			case 'p':
				if (optarg){ 
					periph_num = strtol(optarg, NULL, 0) - 1;
				} else {
					printf("No argument specified for -p\n");
					exit(EXIT_FAILURE);
				}
				break;
			case 'h':
				hflag = 1;
				break;
			case '?':
				printHelp(argv[0]);
				exit(EXIT_FAILURE);
			default:
				printHelp(argv[0]);
				exit(EXIT_FAILURE);
		}
	}

	if ((hflag == 1) || (argc == 1)) {
		printHelp(argv[0]);
		return 0;
	}

	// Extract i2c device
	if (optind < argc) {
		strcpy(i2c_filename, argv[optind]);
	} else {
		printf("I2C Device required.\n");
		exit(EXIT_FAILURE);
	}

	// Open I2C file
	i2c_file = open(i2c_filename, O_RDWR);
	if (i2c_file < 0) {
		printf("Error opening i2c device\n");
		exit(EXIT_FAILURE);
	}

	if ((hflag + wflag + dflag) > 1) {
		printf("Invalid set of options specified.\n");
		printHelp(argv[0]);
		return 0;
	}

	if ((wflag == 1) || (dflag == 1)) {
		if (i2cDetect(i2c_file, peripheral_address[periph_num]) != 0) {
			printf("Peripheral at %X not found\n", peripheral_address[periph_num]);
			exit(EXIT_FAILURE);
		}

		seq_file = open(seq_filename, O_RDWR | O_CREAT, 0666);
		if (seq_file < 0) {
			printf("Error opening sequencing file\n");
			exit(EXIT_FAILURE);
		}
	}

	if (wflag == 1) { // Write sequencer registers from a file to a peripheral
		if (read(seq_file, seq_buf, SEQ_LENGTH) != SEQ_LENGTH) {
			printf("Error reading from sequencer file\n");
			exit(EXIT_FAILURE);
		}

		if (writeMCU(i2c_file, peripheral_address[periph_num], 0x9000,
		             seq_buf, SEQ_LENGTH) != 0) {
			printf("Error writing to the MCU\n");
			exit(EXIT_FAILURE);
		}
	} else if (dflag == 1) { // Dump sequencer registers from a peripheral to a file
		err = dumpSeq(i2c_file, peripheral_address[periph_num], seq_buf);

		if (err < 0) {
			printf("Error reading sequencer registers from device\n");
			exit(EXIT_FAILURE);
		}
		
		if (write(seq_file, seq_buf, SEQ_LENGTH) != SEQ_LENGTH) {
			printf("Error writing to sequencer registers file\n");
			exit(EXIT_FAILURE);
		}
	} else {
		printHelp(argv[0]);
		return 0;
	}

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x230, %rsp            # imm = 0x230
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x1d8(%rbp)
leaq -0x1f0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2eb0
movq 0x417b(%rip), %rax      # 0x6aea
movq %rax, -0x1f8(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x3918(%rip), %rdx      # 0x629c
callq 0x2060
movl %eax, -0x1dc(%rbp)
cmpl $-0x1, %eax
je 0x2b34
movl -0x1dc(%rbp), %eax
movl %eax, -0x20c(%rbp)
subl $0x3f, %eax
je 0x2aff
jmp 0x29af
movl -0x20c(%rbp), %eax
subl $0x64, %eax
je 0x2a61
jmp 0x29c0
movl -0x20c(%rbp), %eax
subl $0x68, %eax
je 0x2af6
jmp 0x29d1
movl -0x20c(%rbp), %eax
subl $0x70, %eax
je 0x2aac
jmp 0x29e2
movl -0x20c(%rbp), %eax
subl $0x77, %eax
jne 0x2b17
jmp 0x29f3
movl $0x1, -0x18(%rbp)
movq 0x85c7(%rip), %rax      # 0xafc8
cmpq $0x0, (%rax)
je 0x2a1f
leaq -0x1c0(%rbp), %rdi
movq 0x85b3(%rip), %rax      # 0xafc8
movq (%rax), %rsi
callq 0x21b0
jmp 0x2a5c
leaq 0x387e(%rip), %rdi      # 0x62a4
xorl %eax, %eax
callq 0x2040
jmp 0x2a2f
movl $0x1, %edi
callq 0x2200
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x200(%rbp)
movl %eax, -0x204(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0x2ef0
jmp 0x2e95
jmp 0x2b2f
movl $0x1, -0x1c(%rbp)
movq 0x8559(%rip), %rax      # 0xafc8
cmpq $0x0, (%rax)
je 0x2a8d
leaq -0x1c0(%rbp), %rdi
movq 0x8545(%rip), %rax      # 0xafc8
movq (%rax), %rsi
callq 0x21b0
jmp 0x2aa7
leaq 0x382e(%rip), %rdi      # 0x62c2
xorl %eax, %eax
callq 0x2040
jmp 0x2a9d
movl $0x1, %edi
callq 0x2200
jmp 0x2b2f
movq 0x8515(%rip), %rax      # 0xafc8
cmpq $0x0, (%rax)
je 0x2ada
movq 0x8508(%rip), %rax      # 0xafc8
movq (%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x2240
subq $0x1, %rax
movl %eax, -0x1d8(%rbp)
jmp 0x2af4
leaq 0x37ff(%rip), %rdi      # 0x62e0
xorl %eax, %eax
callq 0x2040
jmp 0x2aea
movl $0x1, %edi
callq 0x2200
jmp 0x2b2f
movl $0x1, -0x14(%rbp)
jmp 0x2b2f
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2820
jmp 0x2b0d
movl $0x1, %edi
callq 0x2200
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2820
jmp 0x2b25
movl $0x1, %edi
callq 0x2200
jmp 0x2976
cmpl $0x1, -0x14(%rbp)
je 0x2b40
cmpl $0x1, -0x8(%rbp)
jne 0x2b64
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2820
jmp 0x2b4e
movl $0x0, -0x4(%rbp)
movl $0x1, -0x208(%rbp)
jmp 0x2e7d
movq 0x8475(%rip), %rax      # 0xafe0
movl (%rax), %eax
cmpl -0x8(%rbp), %eax
jge 0x2b92
leaq -0xf0(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x845c(%rip), %rcx      # 0xafe0
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x21b0
jmp 0x2bac
leaq 0x3765(%rip), %rdi      # 0x62fe
xorl %eax, %eax
callq 0x2040
jmp 0x2ba2
movl $0x1, %edi
callq 0x2200
xorl %eax, %eax
leaq -0xf0(%rbp), %rdi
movl $0x2, %esi
callq 0x2180
movl %eax, -0x210(%rbp)
jmp 0x2bc7
movl -0x210(%rbp), %eax
movl %eax, -0x1d0(%rbp)
cmpl $0x0, -0x1d0(%rbp)
jge 0x2bf6
leaq 0x3731(%rip), %rdi      # 0x6314
xorl %eax, %eax
callq 0x2040
jmp 0x2bec
movl $0x1, %edi
callq 0x2200
movl -0x14(%rbp), %eax
addl -0x18(%rbp), %eax
addl -0x1c(%rbp), %eax
cmpl $0x1, %eax
jle 0x2c38
leaq 0x3723(%rip), %rdi      # 0x632e
xorl %eax, %eax
callq 0x2040
jmp 0x2c14
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2820
jmp 0x2c22
movl $0x0, -0x4(%rbp)
movl $0x1, -0x208(%rbp)
jmp 0x2e7d
cmpl $0x1, -0x18(%rbp)
je 0x2c48
cmpl $0x1, -0x1c(%rbp)
jne 0x2cef
movl -0x1d0(%rbp), %edi
movslq -0x1d8(%rbp), %rax
movzwl -0x1f8(%rbp,%rax,2), %esi
callq 0x2410
movl %eax, -0x214(%rbp)
jmp 0x2c6a
movl -0x214(%rbp), %eax
cmpl $0x0, %eax
je 0x2c9e
movslq -0x1d8(%rbp), %rax
movzwl -0x1f8(%rbp,%rax,2), %esi
leaq 0x36c6(%rip), %rdi      # 0x6351
xorl %eax, %eax
callq 0x2040
jmp 0x2c94
movl $0x1, %edi
callq 0x2200
xorl %eax, %eax
leaq -0x1c0(%rbp), %rdi
movl $0x42, %esi
movl $0x1b6, %edx            # imm = 0x1B6
callq 0x2180
movl %eax, -0x218(%rbp)
jmp 0x2cbe
movl -0x218(%rbp), %eax
movl %eax, -0x1d4(%rbp)
cmpl $0x0, -0x1d4(%rbp)
jge 0x2ced
leaq 0x3693(%rip), %rdi      # 0x636d
xorl %eax, %eax
callq 0x2040
jmp 0x2ce3
movl $0x1, %edi
callq 0x2200
jmp 0x2cef
cmpl $0x1, -0x18(%rbp)
jne 0x2d9e
movl -0x1d4(%rbp), %edi
leaq -0x1c9(%rbp), %rsi
movl $0x9, %edx
callq 0x2260
movq %rax, -0x220(%rbp)
jmp 0x2d19
movq -0x220(%rbp), %rax
cmpq $0x9, %rax
je 0x2d40
leaq 0x365f(%rip), %rdi      # 0x638c
xorl %eax, %eax
callq 0x2040
jmp 0x2d36
movl $0x1, %edi
callq 0x2200
movl -0x1d0(%rbp), %edi
movslq -0x1d8(%rbp), %rax
movzwl -0x1f8(%rbp,%rax,2), %esi
movl $0x9000, %edx           # imm = 0x9000
leaq -0x1c9(%rbp), %rcx
movl $0x9, %r8d
callq 0x2660
movl %eax, -0x224(%rbp)
jmp 0x2d74
movl -0x224(%rbp), %eax
cmpl $0x0, %eax
je 0x2d99
leaq 0x3629(%rip), %rdi      # 0x63af
xorl %eax, %eax
callq 0x2040
jmp 0x2d8f
movl $0x1, %edi
callq 0x2200
jmp 0x2e6c
cmpl $0x1, -0x1c(%rbp)
jne 0x2e49
movl -0x1d0(%rbp), %edi
movslq -0x1d8(%rbp), %rax
movzwl -0x1f8(%rbp,%rax,2), %esi
leaq -0x1c9(%rbp), %rdx
callq 0x27c0
movl %eax, -0x228(%rbp)
jmp 0x2dd1
movl -0x228(%rbp), %eax
movl %eax, -0x1e0(%rbp)
cmpl $0x0, -0x1e0(%rbp)
jge 0x2e00
leaq 0x35dc(%rip), %rdi      # 0x63c9
xorl %eax, %eax
callq 0x2040
jmp 0x2df6
movl $0x1, %edi
callq 0x2200
movl -0x1d4(%rbp), %edi
leaq -0x1c9(%rbp), %rsi
movl $0x9, %edx
callq 0x2080
movq %rax, -0x230(%rbp)
jmp 0x2e20
movq -0x230(%rbp), %rax
cmpq $0x9, %rax
je 0x2e47
leaq 0x35c4(%rip), %rdi      # 0x63f8
xorl %eax, %eax
callq 0x2040
jmp 0x2e3d
movl $0x1, %edi
callq 0x2200
jmp 0x2e6a
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2820
jmp 0x2e57
movl $0x0, -0x4(%rbp)
movl $0x1, -0x208(%rbp)
jmp 0x2e7d
jmp 0x2e6c
movl $0x0, -0x4(%rbp)
movl $0x1, -0x208(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0x2ef0
movl -0x4(%rbp), %eax
addq $0x230, %rsp            # imm = 0x230
popq %rbp
retq
movq -0x200(%rbp), %rdi
callq 0x22b0
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)