Exemple #1
0
int main()
{
	setupDefault();

	while(1)
	{
//		if(eepromReadByte(0x03, 0x10))
//		{
//			usartSendString(" Received:");
//			usartSend(i2c_received_byte);
//			blinkDbgLed(DBG_LED1);
//		}
//		else
//		{
//			blinkDbgLed(DBG_LED3);
//			i2cRecover();
//		}
		if(eepromReadPage(0x03))
		{
			uint8_t itr = 0;
			while(itr != 0xff)
			{
				usartSend(eeprom_page[itr]);
				itr++;
			}

			blinkDbgLed(DBG_LED1);
		}
		else
		{
			blinkDbgLed(DBG_LED3);
			i2cRecover();
		}

		usartSendString(" XXXXXX");
	}
}
Exemple #2
0
int main (void)
{
        initI2C1 ();
        initUsart ();

#if 0

        /*
         * +----------------+
         * | Initialization |
         * +----------------+
         */

        accelgyro.initialize();
            setClockSource(MPU6050_CLOCK_PLL_XGYRO/*0x01*/);
                /*
                 * Excerpt from domcumentation : Upon power up, the MPU-60X0 clock source defaults to the internal oscillator.
                 * However, it is highly recommended that the device be configured to use one of the gyroscopes. Below is the code
                 * which does it:
                 */
                I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1/*0x6B*/, MPU6050_PWR1_CLKSEL_BIT/*2*/, MPU6050_PWR1_CLKSEL_LENGTH/*3*/, source/*MPU6050_CLOCK_PLL_XGYRO         0x01*/);

            setFullScaleGyroRange(MPU6050_GYRO_FS_250/*0x00*/);
                /*
                 * 0x1b register is used to trigger gyroscope self-test and configure the gyroscopes’ full scale range. Below
                 * we set ful scale to be +/- 250 units (seconds?)
                 */
                I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG/*0x1B*/, MPU6050_GCONFIG_FS_SEL_BIT/*4*/, MPU6050_GCONFIG_FS_SEL_LENGTH/*2*/, range/*0x00*/);

            setFullScaleAccelRange(MPU6050_ACCEL_FS_2/*0x00*/);
                /*
                 * Set accelerometer full scale to be +/- 2g.
                 */
                I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG/*0x1C*/, MPU6050_ACONFIG_AFS_SEL_BIT/*4*/, MPU6050_ACONFIG_AFS_SEL_LENGTH/*2*/, range/*0*/);

            setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
                /*
                 * By default MPU6050 is in sleep mode after powering up. Below we are waking it back on. This
                 * is done using the same register as in first line,
                 */
                I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1/*0x6B*/, MPU6050_PWR1_SLEEP_BIT/*6*/, enabled/*false*/);

        accelgyro.testConnection()
                getDeviceID() == 0x34;
                        /*
                         * This register is used to verify the identity of the device. The contents of WHO_AM_I are
                         * the upper 6 bits of the MPU-60X0’s 7-bit I C address. The Power-On-Reset value of Bit6:Bit1 is 0b110100 == 0x34.
                         */
                        I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I/*0x75*/, MPU6050_WHO_AM_I_BIT/*6*/, MPU6050_WHO_AM_I_LENGTH/*6*/, buffer);
                        return buffer[0];

        /*
         * +----------------+
         * | Main loop      |
         * +----------------+
         */
        int16_t ax, ay, az;
        int16_t gx, gy, gz;

        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

                /*
                 * In MPU-6000 and MPU-6050 Product Specification Rev 3.3 on pages 36 and 37 we read, that I²C reads and writes
                 * can be performed with single byte or multiple bytes. In single byte mode, we issue (after sending slave
                 * address ofcourse) a register address, and send or receive one byte of data. Multiple byte reads and writes, at the
                 * other hand consist of slave address, regiser address and multiple consecutive bytes od data. Slave puts or gets
                 * first byte from the register with the address we've just sent, and increases this addres by 1 after each byte.
                 *
                 * This is very useful in case of accelerometer and gyroscope because manufacturer has set up the apropriate registers
                 * cnsecutively, so one can read accel, internal temp and gyro data in one read command. Below is the code which does
                 * exactly this:
                 */
                I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H/*0x3B*/, 14, buffer);
                *ax = (((int16_t)buffer[0]) << 8) | buffer[1];
                *ay = (((int16_t)buffer[2]) << 8) | buffer[3];
                *az = (((int16_t)buffer[4]) << 8) | buffer[5];
                *gx = (((int16_t)buffer[8]) << 8) | buffer[9];
                *gy = (((int16_t)buffer[10]) << 8) | buffer[11];
                *gz = (((int16_t)buffer[12]) << 8) | buffer[13];

#endif

        // Configuration:
        I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter); // start a transmission in Master transmitter mode
        I2C_write_slow (I2C1, MPU6050_RA_PWR_MGMT_1); // Register address
        I2C_write (I2C1, MPU6050_CLOCK_PLL_XGYRO); // Register value = 0x01. Which means, that DEVICE_RESET, SLEEP, CYCLE and TEMP_DIS are all 0.
        I2C_stop (I2C1);

        I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter);
        I2C_write (I2C1, MPU6050_RA_GYRO_CONFIG);
        I2C_write (I2C1, MPU6050_GYRO_FS_250); // All bits set to zero.
        I2C_stop (I2C1);

        I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter);
        I2C_write (I2C1, MPU6050_RA_ACCEL_CONFIG);
        I2C_write (I2C1, MPU6050_ACCEL_FS_2); // All bits set to zero.
        I2C_stop (I2C1);

        // Simple test if communication is working

        I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter);
        I2C_write (I2C1, MPU6050_RA_WHO_AM_I);
        I2C_stop (I2C1);
        I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Receiver);
        uint8_t whoAmI = I2C_read_nack (I2C1); // read one byte and don't request another byte
        I2C_stop (I2C1);

        if (whoAmI == 0x34) {
                usartSendString (USART1, "Accelerometer has been found!\r\n");
        }
        else {
                usartSendString (USART1, "*NO* Accelerometer has been found!\r\n");
        }

        while (1) {
                I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter);
                I2C_write (I2C1, MPU6050_RA_ACCEL_XOUT_H);
                I2C_stop (I2C1);
                I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Receiver);
                uint16_t ax = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1);
                uint16_t ay = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1);
                uint16_t az = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1);
                uint16_t temp = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1);
                uint16_t gx = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1);
                uint16_t gy = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1);
                uint16_t gz = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_nack (I2C1);
                I2C_stop (I2C1);

                printf ("Accel : (%d, %d, %d), temperature : %d, gyro : (%d, %d, %d)\r\n", ax, ay, az, temp, gx, gy, gz);
        }
}
Exemple #3
0
int receiveCoapMsg(uint8_t* packet, uint16_t port, CoapMsg *coapMsg) {
	coapMsg->coapHdr = (CoapHdr*) packet;

	//Receive UDP request from browser
	coapMsg->coapHdr->udp.destPort = 0;
	do {
		GetPacket(UDPPROTOCOL, packet);
	} while (!(coapMsg->coapHdr->udp.destPort == (uint16_t) HTONS(port)));

	//Parse Token
	uint8_t token[coapMsg->coapHdr->tokenLength];
	coapMsg->token = token;
	memcpy(coapMsg->token, packet + sizeof(CoapHdr),
			coapMsg->coapHdr->tokenLength);

	//Parse options
	uint16_t totalLen; //Total UDP packet length
	totalLen = HTONS(coapMsg->coapHdr->udp.ip.len) + sizeof(EtherNetII) - 2; //-2 Added to make it work with Copper who adds two bytes at the end of the options value
	uint8_t* inputPtr = packet + sizeof(CoapHdr)
			+ coapMsg->coapHdr->tokenLength;
	uint8_t* endPtr = packet + totalLen;
	uint16_t optionNumber = 0;
	coapMsg->options = (CoapOptions) COAP_OPTIONS_INITIALISATION;

	while (inputPtr < endPtr && inputPtr[0] != 0xFF) {
		uint8_t optionByte = inputPtr[0];
		uint16_t optionDelta = optionByte >> 4;
		uint16_t optionLength = optionByte & 0x0F;

		//Process option delta
		switch (optionDelta) {
		case 13:
			inputPtr++;
			optionDelta = (*(inputPtr) - 13) & 0xff;
			break;
		case 14:
			inputPtr++;
			optionDelta = *(inputPtr) - 269;
			inputPtr++;
			break;
		case 15:
			usartSendString("Error: payload marker detected in option delta\r");
			return -1;
			break;
		default:
			break;
		}

		//Process option length
		switch (optionLength) {
		case 13:
			inputPtr++;
			optionLength = (*(inputPtr) - 13) & 0xff;
			break;
		case 14:
			inputPtr++;
			optionLength = *(inputPtr) - 269;
			inputPtr++;
			break;
		case 15:
			usartSendString("Error: message format error\r");
			return -1;
			break;
		default:
			break;
		}

		//Process the option
		uint8_t *optionValue = ++inputPtr;
		optionNumber += optionDelta;

		switch (optionNumber) {
		case COAP_OPTION_URI_PATH:
			coapMsg->options.uriPath.optionLength = optionLength;
			coapMsg->options.uriPath.optionValue = optionValue;
			break;
		case COAP_OPTION_CONTENT_FORMAT:
			coapMsg->options.contentFormat.optionLength = optionLength;
			coapMsg->options.contentFormat.optionValue = optionValue;
		case COAP_OPTION_URI_QUERY:
			coapMsg->options.uriQuery.optionLength = optionLength;
			coapMsg->options.uriQuery.optionValue = optionValue;
		case COAP_OPTION_ACCEPT:
			coapMsg->options.accept.optionLength = optionLength;
			coapMsg->options.accept.optionValue = optionValue;
			break;
		case COAP_OPTION_IF_MATCH:
		case COAP_OPTION_URI_HOST:
		case COAP_OPTION_ETAG:
		case COAP_OPTION_IF_NONE:
		case COAP_OPTION_URI_PORT:
		case COAP_OPTION_LOCATION_PATH:
		case COAP_OPTION_MAX_AGE:
		case COAP_OPTION_LOCATION_QUERY:
		case COAP_OPTION_PROXY_URI:
		case COAP_OPTION_PROXY_SCHEME:
		case COAP_OPTION_SIZE1:
		default:
			usartSendString("Error: Option not supported\r");
			return -1;
			break;
		}

		//Update pointer to next option
		inputPtr += optionLength;
	}
	usartSendString("\rCoAP message received OK\r");
	return 0;
}
Exemple #4
0
void sendCoapMsg(uint8_t* packet, CoapMsg* coapMsg, char *payload) {
	coapMsg->coapHdr = (CoapHdr*) packet;

	//Reset options
	coapMsg->options = (CoapOptions) COAP_OPTIONS_INITIALISATION;

	//Swap source and destination MAC addresses
	memcpy(coapMsg->coapHdr->udp.ip.eth.DestAddrs,
			coapMsg->coapHdr->udp.ip.eth.SrcAddrs, sizeof(deviceMAC));
	memcpy(coapMsg->coapHdr->udp.ip.eth.SrcAddrs, deviceMAC, sizeof(deviceMAC));

	//Swap source and destination IP addresses
	memcpy(coapMsg->coapHdr->udp.ip.dest, coapMsg->coapHdr->udp.ip.source,
			sizeof(deviceIP));
	memcpy(coapMsg->coapHdr->udp.ip.source, deviceIP, sizeof(deviceIP));

	//Swap ports
	uint16_t destPort = coapMsg->coapHdr->udp.destPort;
	coapMsg->coapHdr->udp.destPort = coapMsg->coapHdr->udp.sourcePort;
	coapMsg->coapHdr->udp.sourcePort = destPort;

	//Setup CoAP response
	if (coapMsg->coapHdr->type == COAP_TYPE_CONFIRMABLE)
		coapMsg->coapHdr->type = COAP_TYPE_ACKNOWLEDGEMENT;
	coapMsg->coapHdr->code = COAP_CODE_CONTENT;

	//Payload marker
	uint8_t ff = 0xFF;
	printf("Token length: %u\r", coapMsg->coapHdr->tokenLength);
	memcpy(packet + sizeof(CoapHdr) + coapMsg->coapHdr->tokenLength, &ff, 1);

	//Payload
	uint8_t payloadLen = strlen(payload);
	memcpy(packet + sizeof(CoapHdr) + coapMsg->coapHdr->tokenLength + 1,
			payload, payloadLen);

	//Total packet length
	uint16_t len = sizeof(CoapHdr) + coapMsg->coapHdr->tokenLength + 1
			+ payloadLen;

	//Setup UDP packet
	coapMsg->coapHdr->udp.len = (uint16_t) HTONS((len-sizeof(IPhdr)));
	coapMsg->coapHdr->udp.ip.len = (uint16_t) HTONS((len-sizeof(EtherNetII)));
	coapMsg->coapHdr->udp.ip.ident = 0xdeee;

	//Calculate UDP and IP checksums
	coapMsg->coapHdr->udp.chksum = 0;
	coapMsg->coapHdr->udp.ip.chksum = 0;
	uint16_t pseudochksum = (uint16_t) chksum(UDPPROTOCOL + len - sizeof(IPhdr),
			coapMsg->coapHdr->udp.ip.source, sizeof(deviceIP) * 2);
	uint16_t chk1, chk2;
	chk1 = ~(chksum(pseudochksum, packet + sizeof(IPhdr), len - sizeof(IPhdr)));
	coapMsg->coapHdr->udp.chksum = (uint16_t) HTONS(chk1);
	chk2 = ~(chksum(0, packet + sizeof(EtherNetII),
			sizeof(IPhdr) - sizeof(EtherNetII)));
	coapMsg->coapHdr->udp.ip.chksum = (uint16_t) HTONS(chk2);

	//Send packet
	enc28j60_send_packet(packet, len);
	usartSendString("\rCoAP message sent OK\r");
}
Exemple #5
0
void printCoapMsg(CoapMsg coapMsg) {
	int i;

	//Print type
	usartSendString("Type: ");
	switch (coapMsg.coapHdr->type) {
	case COAP_TYPE_CONFIRMABLE:
		usartSendString("Confirmable\r");
		break;
	case COAP_TYPE_NON_CONFIRMABLE:
		usartSendString("Non-confirmable\r");
		break;
	case COAP_TYPE_ACKNOWLEDGEMENT:
		usartSendString("Acknowledgement\r");
		break;
	case COAP_TYPE_RESET:
		usartSendString("Reset\r");
		break;
	default:
		usartSendString("Print error: Type not recognized\r");
		break;
	}

	//Print code
	usartSendString("Code: ");
	switch (coapMsg.coapHdr->code) {
	case COAP_CODE_EMPTY:
		usartSendString("EMPTY\r");
		break;
	case COAP_CODE_GET:
		usartSendString("GET\r");
		break;
	case COAP_CODE_POST:
		usartSendString("POST\r");
		break;
	case COAP_CODE_PUT:
		usartSendString("PUT\r");
		break;
	case COAP_CODE_DELETE:
		usartSendString("DELETE\r");
		break;
	case COAP_CODE_CONTENT:
		usartSendString("CONTENT\r");
		break;
	default:
		usartSendString("Print error: Method code not recognized\r");
		break;
	}

	//Print message ID
	usartSendString("MID: ");
	printf("%u\r", (uint16_t) HTONS(coapMsg.coapHdr->msgID));

	//Print token
	if (coapMsg.coapHdr->tokenLength) {
		usartSendString("Token: ");
		for (i = 0; i < coapMsg.coapHdr->tokenLength; i++)
			printf("%u", coapMsg.token[i]);
		usartSendString("\r");
	}

	//Print options
	if (coapMsg.options.uriPath.optionLength) {
		usartSendString("Option: Uri-Path\r");
		usartSendString("Option value: ");
		for (i = 0; i < coapMsg.options.uriPath.optionLength; i++)
			usartSend8(coapMsg.options.uriPath.optionValue[i]);
		usartSendString("\r");
	}

	if (coapMsg.options.contentFormat.optionLength) {
		usartSendString("Option: Content-Format\r");
		usartSendString("Option value: ");
		for (i = 0; i < coapMsg.options.contentFormat.optionLength; i++)
			printf("%u", coapMsg.options.contentFormat.optionValue[i]);
		usartSendString("\r");
	}

	if (coapMsg.options.uriQuery.optionLength) {
		usartSendString("Option: Uri-Query\r");
		usartSendString("Option value: ");
		for (i = 0; i < coapMsg.options.uriQuery.optionLength; i++)
			printf("%u", coapMsg.options.uriQuery.optionValue[i]);
		usartSendString("\r");
	}

	if (coapMsg.options.accept.optionLength) {
		usartSendString("Option: Accept\r");
		usartSendString("Option value: ");
		for (i = 0; i < coapMsg.options.accept.optionLength; i++)
			printf("%u", coapMsg.options.accept.optionValue[i]);
		usartSendString("\r");
	}
}
Exemple #6
0
// Called once at startup
//
void mainInit(void) {

	xdata uint8 thisByte = 0xFF;
	xdata uint16 blockSize;

	setIntCount = 23;

	// 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

	// Disable alternate functions for PORTA 0,1,3 & 7.
	PORTACFG = 0x00;

	// 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);
	SYNCDELAY; IFCONFIG = (bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmPORTS);

	// EP4 & EP8 are unused
	SYNCDELAY; EP4CFG = 0x00;
	SYNCDELAY; EP8CFG = 0x00;
	SYNCDELAY; EP4FIFOCFG = 0x00;
	SYNCDELAY; EP8FIFOCFG = 0x00;

	// EP1OUT & EP1IN
	SYNCDELAY; EP1OUTCFG = (bmVALID | bmBULK);
	SYNCDELAY; EP1INCFG = (bmVALID | bmBULK);

	// EP2OUT & EP6IN are quad-buffered bulk endpoints
	SYNCDELAY; EP2CFG = (bmVALID | bmBULK);
	SYNCDELAY; EP6CFG = (bmVALID | bmBULK | bmDIR);

	// Reset FIFOs for EP2OUT & EP6IN
	SYNCDELAY; FIFORESET = bmNAKALL;
	SYNCDELAY; FIFORESET = 2;  // reset EP2OUT
	SYNCDELAY; FIFORESET = 6;  // reset EP6IN
	SYNCDELAY; FIFORESET = 0x00;

	// Arm EP1OUT
	EP1OUTBC = 0x00;

	// Arm the EP2OUT buffers. Done four times because it's quad-buffered
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;  // EP2OUT
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;

	// EP2OUT & EP6IN automatically commit packets
	SYNCDELAY; EP2FIFOCFG = bmAUTOOUT;
	SYNCDELAY; EP6FIFOCFG = bmAUTOIN;

	// Auto-commit 512-byte packets from EP6IN (master may commit early by asserting PKTEND)
	SYNCDELAY; EP6AUTOINLENH = 0x02;
	SYNCDELAY; EP6AUTOINLENL = 0x00;
	
	// Turbo I2C
	I2CTL |= bm400KHZ;

	// Auto-pointers
	AUTOPTRSETUP = bmAPTREN | bmAPTR1INC | bmAPTR2INC;

	// Port lines all inputs...
	IOA = 0xFF;
	OEA = 0x00;
	IOB = 0xFF;
	OEB = 0x00;
	IOC = 0xFF;
	OEC = 0x00;
	IOD = 0xFF;
	OED = 0x00;
	IOE = 0xFF;
	OEE = 0x00;

#ifdef EEPROM
	#include "init.inc"
#endif

#ifdef DEBUG
	usartInit();
	usartSendString("MakeStuff FPGALink/FX2 v1.1\r");
#endif
}
// Read "length" bytes from RAM at "buf", and write them to the attached EEPROM at address "addr".
//
bool promWrite(bool bank, uint16 addr, uint8 length, const __xdata uint8 *buf) {
	__xdata uint8 i;
	const __xdata uint8 i2cAddr = bank ? BANK_1 : BANK_0;

	#ifdef DEBUG
		usartSendString("promWrite(");
		usartSendByte(bank?'1':'0');
		usartSendByte(',');
		usartSendWordHex(addr);
		usartSendByte(',');
		usartSendWordHex(length);
		usartSendByte(')');
		usartSendByte('\r');
	#endif

	// Wait for I2C idle
	//
	while ( I2CS & bmSTOP );

	// Send the WRITE command
	//
	I2CS = bmSTART;
	I2DAT = i2cAddr;  // Write I2C address byte (WRITE)
	if ( promWaitForAck() ) {
		return true;
	}

	// Send the address, MSB first
	//
	I2DAT = MSB(addr);  // Write MSB of address
	if ( promWaitForAck() ) {
		return true;
	}
	I2DAT = LSB(addr);  // Write LSB of address
	if ( promWaitForAck() ) {
		return true;
	}

	// Write the data
	//
	for ( i = 0; i < length; i++ ) {
		I2DAT = *buf++;
		if ( promWaitForDone() ) {
			return true;
		}
	}
	I2CS |= bmSTOP;

	// Wait for I2C idle
	//
	while ( I2CS & bmSTOP );

	do {
		I2CS = bmSTART;
		I2DAT = i2cAddr;  // Write I2C address byte (WRITE)
		if ( promWaitForDone() ) {
			return true;
		}
		I2CS |= bmSTOP;
		while ( I2CS & bmSTOP );
	} while ( !(I2CS & bmACK) );
	
	return false;
}
// Read "length" bytes from address "addr" in the attached EEPROM, and write them to RAM at "buf".
//
bool promRead(bool bank, uint16 addr, uint8 length, __xdata uint8 *buf) {
	__xdata uint8 i;
	const __xdata uint8 i2cAddr = bank ? BANK_1 : BANK_0;

	#ifdef DEBUG
		usartSendString("promRead(");
		usartSendByte(bank?'1':'0');
		usartSendByte(',');
		usartSendWordHex(addr);
		usartSendByte(',');
		usartSendWordHex(length);
		usartSendByte(')');
		usartSendByte('\r');
	#endif

	// Wait for I2C idle
	//
	while ( I2CS & bmSTOP );

	// Send the WRITE command
	//
	I2CS = bmSTART;
	I2DAT = i2cAddr;  // Write I2C address byte (WRITE)
	if ( promWaitForAck() ) {
		return true;
	}
	
	// Send the address, MSB first
	//
	I2DAT = MSB(addr);  // Write MSB of address
	if ( promWaitForAck() ) {
		return true;
	}
	I2DAT = LSB(addr);  // Write LSB of address
	if ( promWaitForAck() ) {
		return true;
	}

	// Send the READ command
	//
	I2CS = bmSTART;
	I2DAT = (i2cAddr | READ);  // Write I2C address byte (READ)
	if ( promWaitForDone() ) {
		return true;
	}

	// Read dummy byte
	//
	i = I2DAT;
	if ( promWaitForDone() ) {
		return true;
	}

	// Now get the actual data
	//
	for ( i = 0; i < (length-1); i++ ) {
		buf[i] = I2DAT;
		if ( promWaitForDone() ) {
			return true;
		}
	}

	// Terminate the read operation and get last byte
	//
	I2CS = bmLASTRD;
	if ( promWaitForDone() ) {
		return true;
	}
	buf[i] = I2DAT;
	if ( promWaitForDone() ) {
		return true;
	}
	I2CS = bmSTOP;
	i = I2DAT;

	return false;
}
Exemple #9
0
// Called once at startup
//
void mainInit(void) {

	xdata uint8 thisByte = 0xFF;
	xdata uint16 blockSize;

	// 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

	// Disable alternate functions for PORTA 0,1,3 & 7.
	PORTACFG = 0x00;

	// 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);

	// EP4 & EP8 are unused
	SYNCDELAY; EP4CFG = 0x00;
	SYNCDELAY; EP8CFG = 0x00;
	SYNCDELAY; EP4FIFOCFG = 0x00;
	SYNCDELAY; EP8FIFOCFG = 0x00;

	// EP1OUT & EP1IN
	SYNCDELAY; EP1OUTCFG = (bmVALID | bmBULK);
	SYNCDELAY; EP1INCFG = (bmVALID | bmBULK);

	// EP2OUT & EP6IN are quad-buffered bulk endpoints
	SYNCDELAY; EP2CFG = (bmVALID | bmBULK);
	SYNCDELAY; EP6CFG = (bmVALID | bmBULK | bmDIR);

	// Reset FIFOs for EP2OUT & EP6IN
	SYNCDELAY; FIFORESET = bmNAKALL;
	SYNCDELAY; FIFORESET = 2;  // reset EP2OUT
	SYNCDELAY; FIFORESET = 6;  // reset EP6IN
	SYNCDELAY; FIFORESET = 0x00;

	// Arm EP1OUT
	EP1OUTBC = 0x00;

	// Arm the EP2OUT buffers. Done four times because it's quad-buffered
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;  // EP2OUT
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;
	SYNCDELAY; OUTPKTEND = bmSKIP | 2;

	// EP2OUT & EP6IN automatically commit packets
	SYNCDELAY; EP2FIFOCFG = bmAUTOOUT;
	SYNCDELAY; EP6FIFOCFG = bmAUTOIN;

	// Auto-commit 512-byte packets from EP6IN (master may commit early by asserting PKTEND)
	SYNCDELAY; EP6AUTOINLENH = 0x02;
	SYNCDELAY; EP6AUTOINLENL = 0x00;
	
	// Turbo I2C
	I2CTL |= bm400KHZ;

	// Auto-pointers
	AUTOPTRSETUP = bmAPTREN | bmAPTR1INC | bmAPTR2INC;

	// Port lines...
	IOA = 0x00;
	OEA = 0x00;
	IOC = 0x00;
	OEC = 0x00;
	IOD = 0x00;
	OED = 0x00;
	IOE = 0x00;
	OEE = 0x00;

	// Disable JTAG mode by default (i.e don't drive JTAG pins)
	jtagSetEnabled(false);

#ifdef BOOT
	promStartRead(false, 0x0000);
	if ( promPeekByte() == 0xC2 ) {
		promNextByte();    // VID(L)
		promNextByte();    // VID(H)
		promNextByte();    // PID(L)
		promNextByte();    // PID(H)
		promNextByte();    // DID(L)
		promNextByte();    // DID(H)
		promNextByte();    // Config byte
		
		promNextByte();    // Length(H)
		thisByte = promPeekByte();
		while ( !(thisByte & 0x80) ) {
			blockSize = thisByte;
			blockSize <<= 8;
			
			promNextByte();  // Length(L)
			blockSize |= promPeekByte();
			
			blockSize += 2;  // Space taken by address
			while ( blockSize-- ) {
				promNextByte();
			}
			
			promNextByte();  // Length(H)
			thisByte = promPeekByte();
		}
		promNextByte();    // Length(L)
		promNextByte();    // Address(H)
		promNextByte();    // Address(L)
		promNextByte();    // Last byte
		promNextByte();    // First byte after the end of the firmware
	}
	jtagSetEnabled(true);
	jtagCsvfInit();
	m_diagnosticCode = jtagCsvfPlay();
	jtagSetEnabled(false);
	thisByte = promPeekByte();
	promNextByte();
	blockSize = promPeekByte();
	promNextByte();
	blockSize <<= 8;
	blockSize |= promPeekByte();
	promNextByte();
	if ( thisByte ) {
		if ( blockSize ) {
			fifoSendPromData(0x10000UL + blockSize);
		}
	} else if ( blockSize ) {
		fifoSendPromData(blockSize);
	}
	promStopRead();
	USBCS &= ~bmDISCON;
#endif

#ifdef DEBUG
	usartInit();
	usartSendString("MakeStuff FPGALink/FX2 v1.1\r");
#endif
	initPorts();
}