#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/f1/spi.h>
#include <libLHP_UART.h>
#include <libLHP_SPI.h>
#include <stdint.h>

#include "mx25.h"

#define SPI_BUF_SZ 128



void clock_setup(){
rcc_clock_setup_in_hse_8mhz_out_24mhz();
}

void gpio_setup(){
rcc_periph_clock_enable(RCC_GPIOC);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
}

uint8_t memaddr[1];
uint8_t buffer[SPI_BUF_SZ];

int main(){
  uint8_t a=0;
  int i,j;
  clock_setup();
  gpio_setup();
  GPIOC_ODR = 0;
  
  setup_UART1();
  setup_SPI1();


  spi_init_master(
                  SPI1,
                  SPI_CR1_BAUDRATE_FPCLK_DIV_256,
                  SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, // 0
                  SPI_CR1_CPHA_CLK_TRANSITION_1,   // 0
                  SPI_CR1_DFF_8BIT,
                  SPI_CR1_MSBFIRST
                  );
  spi_enable_ss_output(SPI1);

  clrscreen_uart(USART1);
  printstr(USART1,"LHP - Bluepill\r\n"__FILE__ "\r\n"  __DATE__ " - " __TIME__ "\r\n");

  for(i=0;i<SPI_BUF_SZ;i++){
    buffer[i] = 0;
  }

  mx25_id(SPI1,buffer);

  print_hex_8 (USART1, buffer[0]);
  printstr_rn(USART1);
  print_hex_8(USART1, buffer[1]);
  print_hex_8_noprefix(USART1, buffer[2]);
  printstr_rn(USART1);

  printstr_blocking(USART1,"---");printstr_rn(USART1);
  if( (buffer[0] == 0xc2) && (buffer[1]== 0x20)){
    printstr(USART1,"Macronix SPI flash found, OK!");
    printstr_rn(USART1);
  }else{
    while(1);
    // ahah not the correct vendor maybe someone counterfeited my product !
    //let's hang
  }

  mx25_readat(SPI1,buffer,0,128);
  print_hexdump_str(USART1,buffer,16);
  if(
     buffer[0] != 'H' ||
     buffer[1] != '4' ||
     buffer[2] != 'C' ||
     buffer[3] != 'K'
     ){
    // we are fresh out of the plant, let's erase our storage and prepare
    // our "unhackable" thing,
    printstr_blocking(USART1,"Initialising SPI flash");
    mx25_sectorerase(SPI1,0);
    for (int i = 0; i < 50; i++)	/* Wait enough. */
     __asm__("nop");

    GPIOC_ODR ^= (1<<13);GPIOC_ODR ^= (1<<13);



    while( (mx25_getstatus(SPI1) & 1) ){

      printstr(USART1,".");
      for (int i = 0; i < 5000; i++)	/* Wait enough. */
        __asm__("nop");
    }
    GPIOC_ODR ^= (1<<13);GPIOC_ODR ^= (1<<13);
    printstr_rn(USART1);
    mx25_getstatus(SPI1);



    //print_hexdump_str(USART1,buffer,50 );
    printstr_rn(USART1);


    //print_hex_8 (USART1, ret);

    buffer[0] = 'H' ;
    buffer[1] = '4';
    buffer[2] = 'C';
    buffer[3] = 'K';
    for(i=0;i<12;i++){
      buffer[4+i] = *(((uint8_t *) 0x1FFFF7E8)+i);
    }

    for(i=16;i<128;i++){
      buffer[i]=buffer[i&0xf];
    }

    mx25_writepage(SPI1,buffer,0,128);

    GPIOC_ODR ^= (1<<13);GPIOC_ODR ^= (1<<13);
    while( (mx25_getstatus(SPI1) & 1) ){
      printstr(USART1,".");
      for (int i = 0; i < 5000; i++)	/* Wait enough. */
        __asm__("nop");
    }
    GPIOC_ODR ^= (1<<13);GPIOC_ODR ^= (1<<13);



  for ( i = 0; i < 1600000; i++)	/* Wait enough */
    __asm__("nop");


  }else{
     printstr_blocking(USART1,"\r\nSPI flash is initialized");printstr_rn(USART1);
  }

  printstr_blocking(USART1,"---");

  while(1){
    GPIOC_ODR ^= (1<<13);
    if(UART1_received_cmd()){

      printstr(USART1,get_receive_buff());
      receive_buff_processed();
      printstr_rn(USART1);

    }



    for ( i = 0; i < 1600000; i++)	/* Wait enough to be visible. */
      __asm__("nop");
  }

}
