// File: /workspace/github_c_makefile_star2_O2/eridanhq[P]miraclelib/miraclelib.c
// Function: ad9173_freq
void ad9173_freq(uint64_t fLO, void *mapped_base)
{
	//uint64_t fDAC, c1, c2, M, N, X, Y, A, B; // need 64-bit computation
	uint64_t X, A, B; // need 64-bit computation
	int i;

	ad9173_freq_calc(fLO, &A, &B, &X); // frequency parameter calculations

	// spi words structure
	unsigned int spi_words[]  = {
		0x000840, 			// DAC0 page
		0x011300, 			// Clear DDSM_FTW_LOAD_ACK
		0x011400 | ( X        & 0xFF),  // X: DDSM_FTW[ 7: 0]
		0x011500 | ((X >>  8) & 0xFF),  // X: DDSM_FTW[15: 8]
		0x011600 | ((X >> 16) & 0xFF),  // X: DDSM_FTW[23:16]
		0x011700 | ((X >> 24) & 0xFF),  // X: DDSM_FTW[31:24]
		0x011800 | ((X >> 32) & 0xFF),  // X: DDSM_FTW[39:32]
		0x011900 | ((X >> 40) & 0xFF),  // X: DDSM_FTW[47:40]
		0x011C00, 			// DDSM_NCO_PHASE_OFFSET[ 7:0]
		0x011D00, 			// DDSM_NCO_PHASE_OFFSET[15:8]
		0x012400 | ( B        & 0xFF),	// B: DDSM_ACC_MODULUS[ 7: 0]
		0x012500 | ((B >>  8) & 0xFF),	// B: DDSM_ACC_MODULUS[15: 8]
		0x012600 | ((B >> 16) & 0xFF),	// B: DDSM_ACC_MODULUS[23:16]
		0x012700 | ((B >> 24) & 0xFF),	// B: DDSM_ACC_MODULUS[31:24]
		0x012800 | ((B >> 32) & 0xFF),	// B: DDSM_ACC_MODULUS[39:32]
		0x012900 | ((B >> 40) & 0xFF),	// B: DDSM_ACC_MODULUS[47:40]
		0x012A00 | ( A        & 0xFF),	// A: DDSM_ACC_DELTA[ 7: 0]
		0x012B00 | ((A >>  8) & 0xFF),	// A: DDSM_ACC_DELTA[15: 8]
		0x012C00 | ((A >> 16) & 0xFF),	// A: DDSM_ACC_DELTA[23:16]
		0x012D00 | ((A >> 24) & 0xFF),	// A: DDSM_ACC_DELTA[31:24]
		0x012E00 | ((A >> 32) & 0xFF),	// A: DDSM_ACC_DELTA[39:32]
		0x012F00 | ((A >> 40) & 0xFF),	// A: DDSM_ACC_DELTA[47:40]
		0x011301, 			// update datapath NCO & FTW words
	};

	int n = NELEMS(spi_words);
	write_reg_tx(32,0x1,mapped_base); // CS select bit
	for (i = 0; i<n; i++)
	{
		//printf("%2d: 0x%X\n", i, spi_words[i]);
		write_reg_tx(33,spi_words[i],mapped_base);
		usleep(500); // 500 usec pause
	}

	/*
	// Debug print statements
	printf("GCD of %" PRIu64 " and %" PRIu64 ": %" PRIu64 "\n", fLO, fDAC, c1);
	printf("M=%" PRIu64 " and N=%" PRIu64 "\n", M,N);
	printf("X=0x%" PRIx64 "\n", X);
	printf("M*2^48 = 0x%" PRIx64 "\n", (M<<48));
	printf("X*N    = 0x%" PRIx64 "\n", X*N);
	printf("Y=0x%" PRIx64 "\n", Y);
	printf("GCD of %" PRIu64 " and %" PRIu64 ": %" PRIu64 "\n", Y, N, c2);

	printf("A=0x%" PRIx64 "\n", A);
	printf("B=0x%" PRIx64 "\n", B);

	printf("Size of int64_t: %d bytes\n", sizeof(c1));
	*/
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rsi, %rbx
leaq 0x68(%rsp), %r14
leaq 0x60(%rsp), %r15
leaq 0x70(%rsp), %r12
movq %r14, %rsi
movq %r15, %rdx
movq %r12, %rcx
callq 0x17af
movabsq $0x1130000000840, %rax  # imm = 0x1130000000840
movq %rax, (%rsp)
movq (%r12), %rcx
movl $0xff, %eax
movl %ecx, %edx
andl %eax, %edx
orl $0x11400, %edx          # imm = 0x11400
movl %edx, 0x8(%rsp)
movl %ecx, %edx
shrl $0x8, %edx
andl %eax, %edx
orl $0x11500, %edx          # imm = 0x11500
movl %edx, 0xc(%rsp)
movl %ecx, %edx
shrl $0x10, %edx
andl %eax, %edx
orl $0x11600, %edx          # imm = 0x11600
movl %edx, 0x10(%rsp)
movl %ecx, %edx
shrl $0x18, %edx
orl $0x11700, %edx          # imm = 0x11700
movl %edx, 0x14(%rsp)
movq %rcx, %rdx
shrq $0x20, %rdx
andl %eax, %edx
orl $0x11800, %edx          # imm = 0x11800
movl %edx, 0x18(%rsp)
shrq $0x28, %rcx
andl %eax, %ecx
orl $0x11900, %ecx          # imm = 0x11900
movl %ecx, 0x1c(%rsp)
movabsq $0x11d0000011c00, %rcx  # imm = 0x11D0000011C00
movq %rcx, 0x20(%rsp)
movq (%r15), %rcx
movl %ecx, %esi
movl %ecx, %edi
movl %ecx, %edx
movq %rcx, %xmm0
andl %eax, %ecx
orl $0x12400, %ecx          # imm = 0x12400
movl %ecx, 0x28(%rsp)
shrl $0x8, %esi
andl %eax, %esi
orl $0x12500, %esi          # imm = 0x12500
movl %esi, 0x2c(%rsp)
shrl $0x10, %edi
andl %eax, %edi
orl $0x12600, %edi          # imm = 0x12600
movl %edi, 0x30(%rsp)
shrl $0x18, %edx
orl $0x12700, %edx          # imm = 0x12700
pshufd $0x44, %xmm0, %xmm1     # xmm1 = xmm0[0,1,0,1]
psrlq $0x20, %xmm0
psrlq $0x28, %xmm1
movsd %xmm0, %xmm1            # xmm1 = xmm0[0],xmm1[1]
movq (%r14), %rcx
movl %ecx, %esi
shrl $0x8, %esi
movd %ecx, %xmm0
movd %esi, %xmm2
punpcklqdq %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0]
shufps $0x28, %xmm2, %xmm1     # xmm1 = xmm1[0,2],xmm2[2,0]
andps 0x735(%rip), %xmm1      # 0x2090
orps 0x73e(%rip), %xmm1      # 0x20a0
movl %edx, 0x34(%rsp)
movups %xmm1, 0x38(%rsp)
movl %ecx, %edx
shrl $0x10, %edx
andl %eax, %edx
orl $0x12c00, %edx          # imm = 0x12C00
movl %edx, 0x48(%rsp)
movl %ecx, %edx
shrl $0x18, %edx
orl $0x12d00, %edx          # imm = 0x12D00
movl %edx, 0x4c(%rsp)
movq %rcx, %rdx
shrq $0x20, %rdx
andl %eax, %edx
orl $0x12e00, %edx          # imm = 0x12E00
movl %edx, 0x50(%rsp)
shrq $0x28, %rcx
andl %eax, %ecx
orl $0x12f00, %ecx          # imm = 0x12F00
movl %ecx, 0x54(%rsp)
movl $0x11301, 0x58(%rsp)    # imm = 0x11301
movl $0x80000020, (%rbx)     # imm = 0x80000020
movl $0x1, 0xcc(%rbx)
xorl %r14d, %r14d
cmpq $0x17, %r14
je 0x19ee
movl (%rsp,%r14,4), %eax
movl $0x80000021, (%rbx)     # imm = 0x80000021
movl %eax, 0xcc(%rbx)
movl $0x1f4, %edi            # imm = 0x1F4
callq 0x1130
incq %r14
jmp 0x19c9
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq