/* pcf8574_for_HD44780.v - takes in control sequences for an HD44780 display
   and outputs data that control a pcf8574 connected to a HD44780 in a standard
   manner over i2c

   This file is part of the 9086 project.

   Copyright (c) 2024 Efthymios Kritikos

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

module pcf8574_for_HD44780(
input wire clock,

input wire pcf_write_req,
input wire pcf_command_data,
input wire [3:0]pcf_data,
output reg pcf_busy=0,
/* verilator lint_off UNUSEDSIGNAL */
input new_backlight,
/* verilator lint_on UNUSEDSIGNAL */
input  backlight_update,

input I2C_BUSY,
output reg I2C_TRANSACT=0,
output reg DIR=0,

output reg [7:0]i2c_data_write
);

reg backlight=1;
reg backlight_latch=0;
reg [3:0]pcf_state=0;

always @(posedge clock) begin
// [ D7 , D6 , D5 , D4 , BACKLIGHT , EN  , WRITE  , COMMAND/DATA ]
	if(backlight_update)
		backlight_latch<=1;
	case(pcf_state)
		4'b0000: begin /*Idle*/
			if(pcf_write_req&&I2C_BUSY==0)begin
				pcf_state<=4'b0001;
				I2C_TRANSACT<=0;
				pcf_busy<=1;
			end else if(backlight_latch&&I2C_BUSY==0)begin
				pcf_state<=4'b1111;
				I2C_TRANSACT<=0;
				pcf_busy<=1;
			end
		end
		4'b0001: begin
			if(I2C_BUSY==0)begin
				i2c_data_write<={pcf_data[3:0],backlight,1'b0,1'b0,pcf_command_data};
				I2C_TRANSACT<=1;
				backlight_latch<=0;
				pcf_state<=4'b0010;
			end
		end
		4'b0010:begin
			if(I2C_BUSY==1)begin
				I2C_TRANSACT<=0;
				pcf_state<=4'b0011;
			end
		end
		4'b0011: begin
			if(I2C_BUSY==0)begin
				i2c_data_write<={pcf_data[3:0],backlight,1'b1,1'b0,pcf_command_data};
				I2C_TRANSACT<=1;
				backlight_latch<=0;
				pcf_state<=4'b0100;
			end
		end
		4'b0100:begin
			if(I2C_BUSY==1)begin
				I2C_TRANSACT<=0;
				pcf_state<=4'b0101;
			end
		end
		4'b0101: begin
			if(I2C_BUSY==0)begin
				i2c_data_write<={pcf_data[3:0],backlight,1'b0,1'b0,pcf_command_data};
				I2C_TRANSACT<=1;
				pcf_state<=4'b0110;
			end
		end
		4'b0110: begin
			if(I2C_BUSY==1)begin
				I2C_TRANSACT<=0;
				pcf_state<=4'b0111;
			end
		end
		4'b0111:begin
			if(I2C_BUSY==0)begin
				pcf_state<=4'b0000;
				pcf_busy<=1'b0;
			end
		end
		4'b1111:begin
			if(I2C_BUSY==1)begin
				pcf_state<=4'b0000;
				I2C_TRANSACT<=1'b0;
				pcf_busy<=1'b0;
			end else begin
				i2c_data_write<={4'b0,backlight,1'b0,1'b0,1'b0};
				backlight_latch<=0;
				I2C_TRANSACT<=1'b1;
				pcf_busy<=1'b1;
			end
		end
		default:begin
			pcf_state<=0;
		end
	endcase
end

endmodule
