/* Copyright 2008, Unpublished Work of Technologic Systems
 * All Rights Reserved.
 *
 * THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
 * PROPRIETARY AND TRADE SECRET INFORMATION OF TECHNOLOGIC SYSTEMS.
 * ACCESS TO THIS WORK IS RESTRICTED TO (I) TECHNOLOGIC SYSTEMS 
 * EMPLOYEES WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE
 * OF THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN TECHNOLOGIC
 * SYSTEMS WHO HAVE ENTERED INTO APPROPRIATE LICENSE AGREEMENTS.  NO
 * PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, COPIED, 
 * DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, CONDENSED, 
 * EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, TRANSFORMED, ADAPTED
 * IN ANY FORM OR BY ANY MEANS, MANUAL, MECHANICAL, CHEMICAL, 
 * ELECTRICAL, ELECTRONIC, OPTICAL, BIOLOGICAL, OR OTHERWISE WITHOUT
 * THE PRIOR WRITTEN PERMISSION AND CONSENT OF TECHNOLOGIC SYSTEMS.
 * ANY USE OR EXPLOITATION OF THIS WORK WITHOUT THE PRIOR WRITTEN
 * CONSENT OF TECHNOLOGIC SYSTEMS COULD SUBJECT THE PERPETRATOR TO
 * CRIMINAL AND CIVIL LIABILITY.
 */

module touchscreen(
  wb_clk_i,
  wb_rst_i,
  wb_cyc_i,
  wb_stb_i,
  wb_we_i,
  wb_adr_i,
  wb_dat_i,
  wb_dat_o,
  wb_ack_o,

  spi_miso_i,
  spi_mosi_o,
  spi_clk_o,
  ad7843_csn_o,
  ad7843_penirqn_i
);

input wb_clk_i, wb_rst_i, wb_cyc_i, wb_stb_i, wb_we_i;
output [15:0] wb_dat_o;
input [15:0] wb_dat_i;
input [31:0] wb_adr_i;
output wb_ack_o;

input spi_miso_i, ad7843_penirqn_i;
output spi_mosi_o, spi_clk_o, ad7843_csn_o;

reg [4:0] count;
reg enable;
reg [15:0] x, y;
reg [2:0] pendown;
reg wb_ack;
reg [15:0] wb_dat;
wire pendown_bit = (pendown == 3'b111);
assign wb_dat_o = wb_dat;
assign wb_ack_o = wb_ack;
always @(posedge wb_clk_i or posedge wb_rst_i) begin
  if (wb_rst_i) begin
    enable <= 1'b0;
    count <= 5'd0;
    wb_ack <= 1'b0;
    wb_dat <= 16'd0;
  end else begin
    enable <= 1'b0;
    count <= count + 1'b1;
    if (count >= 5'd25) begin
      enable <= 1'b1;
      count <= 5'd0;
    end
    if (!wb_ack && wb_cyc_i && wb_stb_i) begin
      wb_ack <= 1'b1;
      if (!wb_adr_i[1]) wb_dat <= {x[15:1], pendown_bit};
      else wb_dat <= {y[15:1], pendown_bit};
    end else wb_ack <= 1'b0;
  end
end

reg [5:0] dclk;
reg [8:0] spi_mosi;
reg [15:0] spi_miso;
reg chan;
reg acq, csn;
assign ad7843_csn_o = csn;
reg [10:0] acq_count;
reg [8:0] pendown_count;
assign spi_mosi_o = spi_mosi[8];
assign spi_clk_o = dclk[0];
always @(posedge wb_clk_i or posedge wb_rst_i) begin
  if (wb_rst_i) begin
    dclk <= 6'd0;
    x <= 16'd0;
    y <= 16'd0;
    csn <= 1'b0;
    spi_mosi <= 9'h90;
    spi_miso <= 16'h0;
    chan <= 1'b0;
    acq <= 1'b0;
    acq_count <= 11'd0;
    pendown_count <= 9'd0;
    pendown <= 3'd0;
  end else if (enable) begin
    if (csn) begin
      pendown_count <= pendown_count + 1'b1;
      if (pendown_count[8]) begin
        pendown <= {pendown[1:0], !ad7843_penirqn_i};
        pendown_count[8] <= 1'b0;
        csn <= 1'b0;
      end
    end else if (dclk[5:0] >= 6'd16 && !acq) begin
      acq_count <= acq_count + 1'b1;
      if (acq_count[10]) begin
        acq <= 1'b1;
        acq_count[10] <= 1'b0;
      end
    end else begin 
      dclk <= dclk + 1'b1;
      if (dclk[0]) spi_mosi <= {spi_mosi[7:0], 1'b0};
      else spi_miso <= {spi_miso[14:0], spi_miso_i};
    end
    
    if (dclk[5:0] >= 6'd49) begin
      if (chan) begin
        spi_mosi <= 9'h90;
        chan <= 1'b0;
        if (pendown == 3'b011) y <= {spi_miso[14:3], 4'd0};
        else y <= y - y[15:4] + spi_miso[14:3];
      end else begin
        csn <= 1'b1;
        chan <= 1'b1;
        spi_mosi <= 9'hd0;
        if (pendown == 3'b011) x <= {spi_miso[14:3], 4'd0};
        else x <= x - x[15:4] + spi_miso[14:3];
      end
      dclk <= 6'd0;
      acq <= 1'b0;
    end

  end
end

endmodule

