/* PRAM - RTC implementation for plus_too */

module rtc (
	input         clk,
	input         reset,

	input  [32:0] timestamp, // unix timestamp
	input         _cs,
	input         ck,
	input         dat_i,
	output reg    dat_o
);

reg   [2:0] bit_cnt;
reg         ck_d;
reg   [7:0] din;
reg   [7:0] cmd;
reg   [7:0] dout;
reg         cmd_mode;
reg         receiving;
reg  [31:0] secs;
reg  [31:0] secs2;
reg   [7:0] ram[20];
reg  [24:0] clocktoseconds;

initial begin
	ram[5'h00] = 8'hA8;
	ram[5'h01] = 8'h00;
	ram[5'h02] = 8'h00;
	ram[5'h03] = 8'h22;
	ram[5'h04] = 8'hCC;
	ram[5'h05] = 8'h0A;
	ram[5'h06] = 8'hCC;
	ram[5'h07] = 8'h0A;
	ram[5'h08] = 8'h00;
	ram[5'h09] = 8'h00;
	ram[5'h0A] = 8'h00;
	ram[5'h0B] = 8'h00;
	ram[5'h0C] = 8'h00;
	ram[5'h0D] = 8'h02;
	ram[5'h0E] = 8'h63;
	ram[5'h0F] = 8'h00;
	ram[5'h10] = 8'h03;
	ram[5'h11] = 8'h88;
	ram[5'h12] = 8'h00;
	ram[5'h13] = 8'h6C;
end

initial secs = 0;

always @(posedge clk) begin
	if (reset) begin
		bit_cnt <= 0;
		receiving <= 1;
		cmd_mode <= 1;
		dat_o <= 1;
	//	sec_cnt <= 0;
	end 
	else begin

		// timestamp is only sent at core load
		if (secs==0)
				secs <= timestamp[31:0] + 2082844800; // difference between unix epoch and mac epoch

		// we need to add one to the seconds
		clocktoseconds<= clocktoseconds + 1'd1;
		if (32499999==clocktoseconds) // every 32mhz we increment secs by one
		begin
			clocktoseconds<=0;
			secs<=secs+1;
		end

		if (_cs) begin
			bit_cnt <= 0;
			receiving <= 1;
			cmd_mode <= 1;
			dat_o <= 1;
		end
		else begin
			ck_d <= ck;

			// transmit at the falling edge
			if (ck_d & ~ck & !receiving)
				dat_o <= dout[7-bit_cnt];
			// receive at the rising edge of ck
			if (~ck_d & ck) begin
				bit_cnt <= bit_cnt + 1'd1;
				if (receiving)
					din <= {din[6:0], dat_i};

				if (bit_cnt == 7) begin
					if (receiving && cmd_mode) begin
						// command byte received
						cmd_mode <= 0;
						receiving <= ~din[6];
						cmd <= {din[6:0], dat_i};
						casez ({din[5:0], dat_i})
							7'b00?0001: dout <= secs[7:0];
							7'b00?0101: dout <= secs[15:8];
							7'b00?1001: dout <= secs[23:16];
							7'b00?1101: dout <= secs[31:24];
							7'b010??01: dout <= ram[{3'b100, din[2:1]}];
							7'b1????01: dout <= ram[din[4:1]];
							default: ;
						endcase
					end
					if (receiving && !cmd_mode) begin
						// data byte received
						casez (cmd[6:0])
							7'b0000001: secs[7:0] <= {din[6:0], dat_i};
							7'b0000101: secs[15:8] <= {din[6:0], dat_i};
							7'b0001001: secs[23:16] <= {din[6:0], dat_i};
							7'b0001101: secs[31:24] <= {din[6:0], dat_i};
							7'b010??01: ram[{3'b100, cmd[3:2]}] <= {din[6:0], dat_i};
							7'b1????01: ram[cmd[5:2]] <= {din[6:0], dat_i};
							default: ;
						endcase
					end
				end
			end
		end
	end
end

endmodule
