Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
148 lines (133 sloc) 4.65 KB
/*
* Copyright (C) 2009-2012 Chris McClelland
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <fx2regs.h>
#include <fx2macros.h>
#include <delay.h>
#include <setupdat.h>
#include <makestuff.h>
#include "../vendorCommands.h"
#include "prom.h"
#include "defs.h"
// Called once at startup
//
void mainInit(void) {
// This is only necessary for cases where you want to load firmware into the RAM of an FX2 that
// has already loaded firmware from an EEPROM. It should definitely be removed for firmwares
// which are themselves to be loaded from EEPROM.
#ifndef EEPROM
RENUMERATE_UNCOND();
#endif
// Return FIFO setings back to default just in case previous firmware messed with them.
SYNCDELAY; PINFLAGSAB = 0x00;
SYNCDELAY; PINFLAGSCD = 0x00;
SYNCDELAY; FIFOPINPOLAR = 0x00;
// Global settings
SYNCDELAY; REVCTL = (bmDYN_OUT | bmENH_PKT);
SYNCDELAY; CPUCS = bmCLKSPD1; // 48MHz
// Drive IFCLK at 48MHz, enable slave FIFOs
SYNCDELAY; IFCONFIG = (bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmFIFOS);
// EP2OUT & EP4IN are handled by firmware, EP6OUT & EP8IN connect to Slave FIFOs
SYNCDELAY; EP2CFG = (bmVALID | bmBULK | bmBUF2X);
SYNCDELAY; EP4CFG = (bmVALID | bmBULK | bmBUF2X | bmDIR);
SYNCDELAY; EP6CFG = (bmVALID | bmBULK | bmBUF2X);
SYNCDELAY; EP8CFG = (bmVALID | bmBULK | bmBUF2X | bmDIR);
// Reset all the FIFOs
SYNCDELAY; FIFORESET = bmNAKALL;
SYNCDELAY; FIFORESET = bmNAKALL | 2; // reset EP2
SYNCDELAY; FIFORESET = bmNAKALL | 4; // reset EP4
SYNCDELAY; FIFORESET = bmNAKALL | 6; // reset EP6
SYNCDELAY; FIFORESET = bmNAKALL | 8; // reset EP8
SYNCDELAY; FIFORESET = 0x00;
// Arm the OUT buffers. Done twice because they're double-buffered
SYNCDELAY; OUTPKTEND = bmSKIP | 2; // EP2OUT
SYNCDELAY; OUTPKTEND = bmSKIP | 2;
SYNCDELAY; OUTPKTEND = bmSKIP | 6; // EP6OUT
SYNCDELAY; OUTPKTEND = bmSKIP | 6;
// EP2OUT & EP4IN handled by firmware, so no FIFOs
SYNCDELAY; EP2FIFOCFG = 0x00;
SYNCDELAY; EP4FIFOCFG = 0x00;
// EP6OUT & EP8IN need to be synchronised anyway, so no FIFOs yet
SYNCDELAY; EP6FIFOCFG = 0x00;
SYNCDELAY; EP8FIFOCFG = 0x00;
// Auto-commit 512-byte packets from EP8IN (master may commit early by asserting PKTEND)
SYNCDELAY; EP8AUTOINLENH = 0x02;
SYNCDELAY; EP8AUTOINLENL = 0x00;
}
// Called repeatedly while the device is idle
//
void mainLoop(void) { }
// Called when a vendor command is received
//
uint8 handleVendorCommand(uint8 cmd) {
switch(cmd) {
// Perform the four arithmetic operations on the incoming wValue & wIndex words
//
case CMD_CALCULATOR:
if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) {
xdata uint16 num1 = SETUP_VALUE();
xdata uint16 num2 = SETUP_INDEX();
uint16 *response = (uint16*)EP0BUF;
while ( EP0CS & bmEPBUSY );
response[0] = num1 + num2;
response[1] = num1 - num2;
response[2] = num1 * num2;
response[3] = num1 / num2;
EP0BCH = 0;
SYNCDELAY;
EP0BCL = 8;
}
return true;
// Command to talk to the EEPROM
//
case CMD_READ_WRITE_EEPROM:
if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) {
// It's an IN operation - read from prom and send to host
xdata uint16 address = SETUP_VALUE();
xdata uint16 length = SETUP_LENGTH();
xdata uint16 chunkSize;
xdata uint8 i;
while ( length ) {
while ( EP0CS & bmEPBUSY );
chunkSize = length < EP0BUF_SIZE ? length : EP0BUF_SIZE;
for ( i = 0; i < chunkSize; i++ ) {
EP0BUF[i] = 0x23;
}
promRead(address, chunkSize, EP0BUF);
EP0BCH = 0;
SYNCDELAY;
EP0BCL = chunkSize;
address += chunkSize;
length -= chunkSize;
}
} else if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) {
// It's an OUT operation - read from host and send to prom
xdata uint16 address = SETUP_VALUE();
xdata uint16 length = SETUP_LENGTH();
xdata uint16 chunkSize;
while ( length ) {
EP0BCL = 0x00; // allow pc transfer in
while ( EP0CS & bmEPBUSY ); // wait for data
chunkSize = EP0BCL;
promWrite(address, chunkSize, EP0BUF);
address += chunkSize;
length -= chunkSize;
}
}
return true;
}
return false; // unrecognised command
}
Something went wrong with that request. Please try again.