Main Page | Modules | Related Pages | Examples

turboadapter/module-src/btldr.c

/*
 * Turbo Programmer Utilities, turbo-prog-utils, www.bladox.com 
 *
 * Copyright (C) 2004 BLADOX, s.r.o.
 *
 * 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 2, 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.
 */

#include <config.h>
#include <tprog/tprog.h>
#include <stdlib.h>
#include <avr/interrupt.h>

#include "turboadapter.h"
#include "btldr.h"

#define DEFAULT_BTLDR_CLK_DIV (2)
#define DEFAULT_F (372)
#define DEFAULT_D (1)
#define DEFAULT_DIVIDER (DEFAULT_F/DEFAULT_D)
u16 actualUbrr;

#define BTLDR_TX_SM_STATE1 (1)
#define BTLDR_TX_SM_STATE2 (2)
u8 btldrUartTxStateMachine;

#define BTLDR_UART_RX_FIFO_SIZE 8
u8 btldrUartRxFifo[BTLDR_UART_RX_FIFO_SIZE];
u8 btldrUartRxFifoNumOfChars;
u8 btldrUartRxFifoTail;
u8 btldrUartRxFifoHead;

void init_vars ()
{
  btldrUartRxFifoHead = 0;
  btldrUartRxFifoTail = 0;
  btldrUartRxFifoNumOfChars = 0;

  actualUbrr = ((DEFAULT_BTLDR_CLK_DIV * DEFAULT_DIVIDER) / 8) - 1;

  btldrUartTxStateMachine = BTLDR_TX_SM_STATE1;
}

void init_btldrUart (void)
{
  //set mode to double speed
  outb (BTLDR_UART_UCSRA, 0x02);

  // enable receive complete interrupt
  // disable transmit complete interrupt
  // enable receiver
  // disable transmitter because of RXD and TXD connected together
  // to not output log.1 to TXD and RXD
  // we enable transmitter before each char will be send
  outb (BTLDR_UART_UCSRB, 0x90);

  // asynchronous mode
  // 8 bit data, even parity, 1 stop bit
  outb (BTLDR_UART_UCSRC, 0x26);

  // set baud rate register to DEFAULT_DIVIDER
  outb (BTLDR_UART_UBRRH, (actualUbrr >> 8));
  outb (BTLDR_UART_UBRRL, (actualUbrr & 0xFF));
}

u8 btldrRxChars (void)
{
  u8 tmpRxChars;

  cli ();
  tmpRxChars = btldrUartRxFifoNumOfChars;
  sei ();
  return tmpRxChars;
}

u8 btldrRxGetChar (void)
{
  u8 tmpTail;

  cli ();
  if (btldrUartRxFifoNumOfChars > 0)
  {
    btldrUartRxFifoNumOfChars--;
    sei ();
    tmpTail = btldrUartRxFifoTail;
    if (btldrUartRxFifoTail < (BTLDR_UART_RX_FIFO_SIZE - 1))
      btldrUartRxFifoTail++;
    else
      btldrUartRxFifoTail = 0;

    return btldrUartRxFifo[tmpTail];
  }
  else
  {
    sei ();
    return 0;
  }
}

void btldrTxSendChar (u8 txValue)
{
  u8 txValueTmp;
  u8 iTmp;
  u8 interrupts;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));

  //cli();
  txValueTmp = txValue;

  if (btldrUartTxStateMachine == BTLDR_TX_SM_STATE1)
  {
    // execute delay before transmitting char
    //do delay interval
    delayMs (3);
    btldrUartTxStateMachine = BTLDR_TX_SM_STATE2;
  }

  // disable receive complete interrupt
  // disable receiver
  outb (BTLDR_UART_UCSRB, (inb (BTLDR_UART_UCSRB) & 0x6F));

  //TXD1 pin to log.1
  sbi (BTLDR_TXD_PORT, BTLDR_TXD_PORT_PIN);

  //TXD1 pin change direction to output only when transmitting char
  sbi (BTLDR_TXD_DDR, BTLDR_TXD_DDR_DD);

  // enable transmitter
  outb (BTLDR_UART_UCSRB, (inb (BTLDR_UART_UCSRB) | 0x08));

  // send txValueTmp to UDR register
  sbi (BTLDR_UART_UCSRA, TXC);
  outb (BTLDR_UDR, txValueTmp);
  loop_until_bit_is_set (BTLDR_UART_UCSRA, TXC);
  sbi (BTLDR_UART_UCSRA, TXC);

  // disable transmitter
  outb (BTLDR_UART_UCSRB, (inb (BTLDR_UART_UCSRB) & 0xF7));

  // set TXD1 pin to log.1
  sbi (BTLDR_TXD_PORT, BTLDR_TXD_PORT_PIN);

  //TXD1 pin change direction to input to allow receiving
  cbi (BTLDR_TXD_DDR, BTLDR_TXD_DDR_DD);

  // clear TXC flag (write log.1 to it)
  sbi (BTLDR_UART_UCSRA, TXC);

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();
  // enable receive complete interrupt
  // enable receiver
  outb (BTLDR_UART_UCSRB, (inb (BTLDR_UART_UCSRB) | 0x90));
}

void init_turboadapter_btldr_port ()
{
  led_on (LED_TFM);

  //DEBUG_SS_MCU change direction to output 
  sbi (DEBUG_SS_MCU_DDR, DEBUG_SS_MCU_DDR_DD);

  // RESETn pin stays output and set it to log.1
  sbi (PROG_RESETn_PORT, PROG_RESETn_PORT_PIN);
  sbi (PROG_RESETn_DDR, PROG_RESETn_DDR_DD);

  //PROG_DEBUG_RESETn_ENABLE pin set it to log.0
  //(in BTLDR mode RESETn is connected)
  ext_cbi (EXT_PROG_DEBUG_RESETn_ENABLE_PORT,
           EXT_PROG_DEBUG_RESETn_ENABLE_PORT_PIN);

  delayMs (200);

  // clear RXC flag (write log.1 to it)
  sbi (BTLDR_UART_UCSRA, RXC);

  // clear TXC flag (write log.1 to it)
  sbi (BTLDR_UART_UCSRA, TXC);

  // set baud rate to enhanced value from PTS
  outb (BTLDR_UART_UBRRH, (actualUbrr >> 8));
  outb (BTLDR_UART_UBRRL, (actualUbrr & 0xFF));

  //PROG_DEBUG_CLKA_ENABLE set it to log.1
  //(in BTLDR_MODE CLKA is connected)
  ext_sbi (EXT_PROG_DEBUG_CLKA_ENABLE_PORT,
           EXT_PROG_DEBUG_CLKA_ENABLE_PORT_PIN);

  delayMs (10);

  //BTLDR_RX
  //let it set to input
  //set pin to log.1
  sbi (BTLDR_RXD_PORT, BTLDR_RXD_PORT_PIN);
  cbi (BTLDR_RXD_DDR, BTLDR_RXD_DDR_DD);

  //BTLDR_TX
  //let it set to output
  //set pin to log.0
  cbi (BTLDR_TXD_PORT, BTLDR_TXD_PORT_PIN);
  sbi (BTLDR_TXD_DDR, BTLDR_TXD_DDR_DD);

  //BTLDR_ENABLE
  //set pin to log.1
  //(in BTLDR_MODE BTLDR_RX and BTLDR_TX are connected)
  ext_sbi (EXT_BTLDR_ENABLE_PORT, EXT_BTLDR_ENABLE_PORT_PIN);

  delayMs (10);

  //PROG_DEBUG_VCC_ENABLE set it to log.0
  //(in BTLDR_MODE we must apply power after all unecessary signals were disconnected)
  ext_cbi (EXT_PROG_DEBUG_VCC_ENABLE_PORT,
           EXT_PROG_DEBUG_VCC_ENABLE_PORT_PIN);

//EXTRA RESET-------------------------------
  delayMs (200);

  // RESETn pin stays output and set it to log.0
  cbi (PROG_RESETn_PORT, PROG_RESETn_PORT_PIN);
  sbi (PROG_RESETn_DDR, PROG_RESETn_DDR_DD);

  //PROG_DEBUG_RESETn_ENABLE pin set it to log.1
  //(in BTLDR mode RESETn is connected)
  ext_sbi (EXT_PROG_DEBUG_RESETn_ENABLE_PORT,
           EXT_PROG_DEBUG_RESETn_ENABLE_PORT_PIN);

  delayMs (100);

  // RESETn pin stays output and set it to log.1
  sbi (PROG_RESETn_PORT, PROG_RESETn_PORT_PIN);
  sbi (PROG_RESETn_DDR, PROG_RESETn_DDR_DD);

  //PROG_DEBUG_RESETn_ENABLE pin set it to log.0
  //(in BTLDR mode RESETn is disconnected)
  ext_cbi (EXT_PROG_DEBUG_RESETn_ENABLE_PORT,
           EXT_PROG_DEBUG_RESETn_ENABLE_PORT_PIN);

//EXTRA RESET-------------------------------

  delayMs (500);

  //remove any char pending in btldf rx fifo
  while (btldrRxChars () != 0)
    btldrRxGetChar ();

  delayMs (10);

  //BTLDR_TX
  //let it set to input
  //set pin to log.1
  sbi (BTLDR_TXD_PORT, BTLDR_TXD_PORT_PIN);
  cbi (BTLDR_TXD_DDR, BTLDR_TXD_DDR_DD);

  delayMs (10);
}

void btldr_uart_irq ()
{
  // next BTLDR char transmit will execute delay before transmitting char
  btldrUartTxStateMachine = BTLDR_TX_SM_STATE1;

  if (btldrUartRxFifoNumOfChars == BTLDR_UART_RX_FIFO_SIZE)
  {
  }
  else
  {
    btldrUartRxFifo[btldrUartRxFifoHead] = inb (BTLDR_UDR);

    btldrUartRxFifoNumOfChars++;
    if (btldrUartRxFifoHead < (BTLDR_UART_RX_FIFO_SIZE - 1))
      btldrUartRxFifoHead++;
    else
      btldrUartRxFifoHead = 0;
  }
}

void btldr_flash_page (USB_Data * data, u8 * buf)
{
  u16 i;

  led_on (LED_NO);

  btldrTxSendChar (UCMD_BTLDR_MODE_WRITE_PAGE_FLASH);
  btldrTxSendChar (data->buf[0]);
  btldrTxSendChar (data->buf[1]);

  for (i = 0; i < 256; i++)
    btldrTxSendChar (data->buf[2 + i]);

  while (btldrRxChars () == 0);
  buf[0] = btldrRxGetChar ();

  led_on (LED_TFM);

  usb_send (NO_ERROR, 1, buf);
}


Copyright © 2004 BLADOX
Turbo Programmer version 2.0