module bldc (
  input clk,
  output dbg_tx,
  output if_int,

  output adc_ss,
  output adc_sck,
  input adc_so,
  output adc_si
  );

reg [7:0] dbg_buf = 0;
reg dbg_buf_vld = 0;
wire dbg_tx_rdy;

reg [15:0] adc_vals[3:0];
reg [1:0] vals_idx = 0;
initial begin
  adc_vals[0] = 0;
  adc_vals[1] = 0;
  adc_vals[2] = 0;
  adc_vals[3] = 0;
end

wire [1:0] adc_channel;
wire [11:0] adc_val;
wire adc_vld;
reg adc_ack = 0;

adc_driver adc0(
  .clk(clk),
  .rst(1'b0),
  .so(adc_so),
  .si(adc_si),
  .ss(adc_ss),
  .sck(adc_sck),

  .channel(adc_channel),
  .val(adc_val),
  .vld(adc_vld),
  .ack(adc_ack)
  );

uart_tx_115200 dbg(
  .clk_25mhz(clk),
  .rst(1'b0),
  .tx(dbg_tx),
  .tx_buf(dbg_buf),
  .vld(dbg_buf_vld),
  .rdy(dbg_tx_rdy)
  );

reg [7:0] tmp3 = 0;
reg [7:0] tmp2 = 0;
reg [7:0] tmp = 0;
assign if_int = tmp[3];

reg uart_end = 0;
reg uart_bsy = 0;

// stores {cur_channel_idx, cur_nibble}
reg [3:0] cur_idx = 0;

reg [15:0] cur_channel;
reg [3:0] cur_nibble;
reg [7:0] nibble_hex;

always @(posedge clk) begin
  cur_channel <= adc_vals[cur_idx[3:2]];

  case (cur_idx[1:0])
    2'b11: cur_nibble <= cur_channel[3:0];
    2'b10: cur_nibble <= cur_channel[7:4];
    2'b01: cur_nibble <= cur_channel[11:8];
    2'b00: cur_nibble <= cur_channel[15:12];
  endcase

  case (cur_nibble)
    4'h0: nibble_hex <= 48;
    4'h1: nibble_hex <= 49;
    4'h2: nibble_hex <= 50;
    4'h3: nibble_hex <= 51;
    4'h4: nibble_hex <= 52;
    4'h5: nibble_hex <= 53;
    4'h6: nibble_hex <= 54;
    4'h7: nibble_hex <= 55;
    4'h8: nibble_hex <= 56;
    4'h9: nibble_hex <= 57;
    4'ha: nibble_hex <= 97;
    4'hb: nibble_hex <= 98;
    4'hc: nibble_hex <= 99;
    4'hd: nibble_hex <= 100;
    4'he: nibble_hex <= 101;
    4'hf: nibble_hex <= 102;
  endcase
end

always @(posedge clk) begin
  tmp <= tmp + 1;
  if (&tmp) begin
    tmp2 <= tmp2 + 1;
    if (&tmp2)
      tmp3 <= tmp3 + 1;
  end

  // 25 MHz / 2^(8+8+7) = 3 Hz
  if (&tmp & &tmp2 & &tmp3[6:0]) begin
    uart_bsy <= 1;
    cur_idx <= 0;
  end

  if (dbg_tx_rdy) begin
    if (uart_bsy & ~dbg_buf_vld) begin
      if (~uart_end) begin
        // write the ADC data to the UART
        //dbg_buf <= cur_idx;
        dbg_buf <= nibble_hex;
        dbg_buf_vld <= 1;

        cur_idx <= cur_idx + 1;
        if (&cur_idx)
          uart_end <= 1;
      end else begin
        // write newline
        dbg_buf <= 8'h0d;
        dbg_buf_vld <= 1;

        uart_end <= 0;
        uart_bsy <= 0;
      end
    end
  end else begin
    dbg_buf_vld <= 0;
  end

  if (adc_vld) begin
    adc_ack <= 1;
    vals_idx <= vals_idx + 1;
    if (~uart_bsy) begin
      adc_vals[vals_idx] <= {adc_channel, adc_val};
    end
  end else begin
    adc_ack <= 0;
  end
end

endmodule