/*
 * USBXpress_Echo_main.c
 *
 * Main routine for USBXpress Echo example.
 *
 * This example echos any data sent over usb back up to the host.
 * It also blinks an led at 1Hz to indicate that the core is running.
 *
 */

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <SI_EFM8UB1_Register_Enums.h>                // SFR declarations
#include "USBXpress.h"
#include "descriptor.h"
#include <stdint.h>

//---------------------------------------------
// Мое
//-----------------------------------------
//  Bit Definitions
sbit  RST067  =  P0^6;  //  Сброс C8051F067.
sbit MOSI  =  P1^1;

data  uint8_t  j,k,INB,N,M;
data  uint16_t  i,L;

xdata uint8_t INARRAY[900];  //Входной массив  uint8_t
//--------------------------------------------

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
void Delay (void);
void Sysclk_Init (void);
void myAPICallback(void);

void Port_Init(void);      //  Initialize Ports Pins and Enable Crossbar
void Init_SPI(void);
void outspi(unsigned char byte);
unsigned char inspi(void);
void HSSPI (void);
void DEL1000(void);
/**************************************************************************//**
 * @breif Main loop
 *
 * The main loop sets up the device and then waits forever. All active tasks
 * are ISR driven.
 *
 *****************************************************************************/
void main (void)
{
  //Disable WDT
  WDTCN = 0xDE;
  WDTCN = 0xAD;
  //PCA0MD &= ~0x40;

  VDM0CN = VDM0CN_VDMEN__ENABLED;            // Enable VDD Monitor
  Delay ();                                  // Wait for VDD Monitor to stabilize
  RSTSRC = RSTSRC_PORSF__SET;                // Enable VDD Monitor as a reset source

  Sysclk_Init ();                           // Initialize system clock
  Port_Init ();                             // Initialize crossbar and GPIO
  Init_SPI();

  // USBXpress Initialization
  USB_Init(&InitStruct);

  // Enable USBXpress API interrupts
  API_Callback_Enable(myAPICallback);
//------------
  RST067=0;   // RESET C8051F067.
  DEL1000();
//  RST067=1;
//  DEL1000();  // Run C8051F067.
//---------
  N=0;
  j=0;
  M=0;

  IE_EA = 1;       // Enable global interrupts

  while (1);  // Spin forever
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
/**************************************************************************//**
 * @brief USBXpress callback
 *
 * This function is called by USBXpress. In this example any received data
 * sent back up to the host.
 *
 *****************************************************************************/
  USBXpress_API_CALLBACK(myAPICallback)
{
   uint32_t INTVAL = Get_Callback_Source();

     if (INTVAL  &  DEVICE_OPEN)        //  RX Complete, RX file state
     {
      if (N==0) {

         RST067=1;    // Run C8051F067.

        Block_Read(INARRAY, 64, &L); //read
                j++;          // 64 times for 64 bytes (64*64=4096 bytes).
                N=1;
                }
     }

     if (INTVAL  &  RX_COMPLETE)        //  RX Complete, RX file state
     {
                Block_Read(INARRAY, 64, &L); //read
                j++;          // 64 times for 64 bytes (64*64=4096 bytes).

               if (j==64)
               {
//===================================================
// Пропуск обмена по SPI.
//------------------------
      //    for (i=0;i<64;i++) {        // Это будет
      //  INARRAY[1023-i]=INARRAY[i];   // сделано
      //         }                      // в C8051f067.
      //    goto AAA;
//===================================================
      HSSPI();
//--------------------------------------------------
      for (k=0;k<4;k++) {            // Вывели по SPI
           for (i=0;i<1024;i++) {    // в C8051f067
                outspi(INARRAY[i]);  // входной массив
           }                         // INARRAY[i] 1024 байт
      }                              // 4 раза.
//---------------------------------------------------
      outspi(0xff);                  //Холостой вывод байта.
      SPI0CN0_SPIEN=0;
      SPI0CN0_SPIEN=1;
//---------------------------------------------------
      for (k=0;k<4;k++) {            // Приняли по SPI
           for (i=0;i<1024;i++) {    // из C8051f067
                INARRAY[i]=inspi();  // массив 1024 байт и записали
           }                         // его в INARRAY[i]
      }                              // 4 раза.
//========================================================
//AAA:
//========================================================
      Block_Write(INARRAY, 1024, &L);
           M++;
//--------------------------------
           }           //от if (j==64)
      }

   if  (INTVAL  &  TX_COMPLETE)
    {
           if (M != 4)
            {
          Block_Write(INARRAY, 1024, &L);
          M++;
           }
           else// if (M==4)
            {
            j=0;
            Block_Read(INARRAY, 64, &L); //read
            j++;          // 64 times for 64 bytes (64*64=4096 bytes).
            N=1;
            M=0;
             }
   }

     if (INTVAL & DEVICE_CLOSE)
   {
   N=0;
   j=0;
   M=0;
   }

}

/**************************************************************************//**
 * @ clock initialization
 *
 * Set fastest system clock (48Mhz)
 *****************************************************************************/
void Sysclk_Init (void)
{
  SFRPAGE = 0x10;
  HFOCN  = HFOCN_HFO1EN__ENABLED;      // Enable 48Mhz osc
  CLKSEL = CLKSEL_CLKDIV__SYSCLK_DIV_2 // Select hfosc/2 (need 24Mhz before switching to 48Mhz)
         | CLKSEL_CLKSL__HFOSC1;
  CLKSEL = CLKSEL_CLKDIV__SYSCLK_DIV_1 // Select hfosc/1
         | CLKSEL_CLKSL__HFOSC1;
  SFRPAGE = 0x0;
}
/**************************************************************************//**
 * @breif Port initialization
 *
 *****************************************************************************/
void Port_Init()
{
    // P0.0  -  Skipped,     Open-Drain, Digital
    // P0.1  -  Skipped,     Open-Drain, Digital
    // P0.2  -  Skipped,     Open-Drain, Digital
    // P0.3  -  Skipped,     Open-Drain, Digital
    // P0.4  -  Skipped,     Open-Drain, Digital
    // P0.5  -  Skipped,     Open-Drain, Digital
    // P0.6  -  RST067 Skipped,     Push-Pull,  Digital
    // P0.7  -  SCK  (SPI0), Open-Drain, Digital

    // P1.0  -  MISO (SPI0), Push-Pull,  Digital
    // P1.1  -  MOSI (SPI0), Open-Drain, Digital
    // P1.2  -  NSS  (SPI0), Open-Drain, Digital(4-wire)

    // P1.3  -  Unassigned,  Open-Drain, Digital
    // P1.4  -  Unassigned,  Open-Drain, Digital
    // P1.5  -  Unassigned,  Open-Drain, Digital
    // P1.6  -  Unassigned,  Open-Drain, Digital
    // P1.7  -  Unassigned,  Open-Drain, Digital
    // P2.0  -  Unassigned,  Open-Drain, Digital
    // P2.1  -  Unassigned,  Open-Drain, Digital
    // P2.2  -  Unassigned,  Open-Drain, Digital
    // P2.3  -  Unassigned,  Open-Drain, Digital

    P0MDOUT   = 0x40; // V
    P1MDOUT   = 0x01; // V
    P0SKIP    = 0x7F; // V
    XBR0      = 0x02; // SPI Enable in Cross Bar
    //  XBR1      = 0x40; - XBARE=1 для 321
    XBR2  =  0x40;//(= XBR2_XBARE__ENABLED) XBARE=1-Crossbar enabled-для UB1
}
/**************************************************************************//**
 * @breif delay for approximately 1ms @ 48Mhz
 *
 *****************************************************************************/
void Delay (void)
{
   int16_t x;
   for (x = 0; x < 500; x)
   {
      x++;
   }
}
//-----------
void Init_SPI()
{
   SPI0CN0    = 0x04;//0x05 - SPI EN и 0x04, если SPI disable - 4 wire
   // SPI0CN0    = 0x00;//0x01 - SPI EN и 0x00 - SPI disable -3 wire
    MOSI  =  1;
}
//-----------
void DEL1000() {
    unsigned int i;
    for (i=0;i<5000;i++) {}
    }
//--------------------------------------
void HSSPI (void) {
     while(!MOSI);  //Только для 3-wire режима.В 4-wire
     while(MOSI);   //режиме синхронизация необязятельна,
                    //но от этого хуже не будет .
//--------------------------------------------
    SPI0CN0_SPIEN=1;
    while (inspi()!=0x0f);

     outspi(0x40);
     }
//--------------------------------
void outspi(unsigned char byte) {
   SPI0DAT=byte;  // Вывод байта по SPI.
//   while (!SPIF); // Ожидание окончания вывода байта
//   SPIF=0;        // Сброс флага окончания передачи.
   while (!SPI0CN0_SPIF);               // Step1.3: Wait for end of transfer
   SPI0CN0_SPIF     = 0;                // Step1.4: Clear the SPI intr. flag

   }
//-----------------
   unsigned char inspi() {
   unsigned char byte;
   SPI0DAT=0;     // Ввод байта в микроконтроллер.
//   while (!SPIF); // Ожидание окончания ввода байта
//   SPIF=0;        // Сброс флага окончания приема.
   while (!SPI0CN0_SPIF);      // Step1.3: Wait for end of transfer
   SPI0CN0_SPIF = 0;           // Step1.4: Clear the SPI intr. flag

   byte=SPI0DAT;
   return(byte);
   }
//----------------

