Пример #1
0
Word Story::read(OperandType operandType)
{
	switch(operandType)
	{
		case OperandType::Large:
			return readNextWord();

		case OperandType::Small:
			return readNextByte();

		case OperandType::Variable:
		{
			auto variableID = readNextByte();
			return loadVariable(variableID);
		}

		case OperandType::Omitted:
		{
			throw Exception("Omitted unexpected");
		}

		default:
		{
			throw Exception("unexpected operand type");
		}
	}
}
Пример #2
0
OpcodeDetails Story::decode()
{
	auto baseAddress = m_PC;

	const Byte value = readNextByte();
	auto opcodeForm=ToOpcodeForm(value);

	if(opcodeForm == OpcodeForm::Short)
	{
		auto operandCount = ((value & 48) == 48 ? OperandCount::OP0 : OperandCount::OP1);

		// The opcode is in the bottom 4 bits
		return OpcodeDetails(baseAddress, value, value & 15, opcodeForm, operandCount);
	}

	if(opcodeForm == OpcodeForm::Long)
	{
		auto operandCount=OperandCount::OP2;
		
		// The opcode is in the bottom 5 bits
		return OpcodeDetails(baseAddress,value,value & 31, opcodeForm, operandCount);
	}

	if(opcodeForm == OpcodeForm::Variable)
	{
		auto operandCount = ((value & 32) ? OperandCount::Variable : OperandCount::OP2);

		// The opcode is in the bottom 5 bits
		return OpcodeDetails(baseAddress, value, value & 31, opcodeForm, operandCount);
	}

	if(opcodeForm == OpcodeForm::Extended)
	{
		auto operandCount = OperandCount::Variable;

		// The next byte has the opcode
		Byte opcode = readNextByte();

		return OpcodeDetails(baseAddress, value, opcode, opcodeForm, operandCount);
	}

	throw Exception("unexpected opcode form");
}
Пример #3
0
BranchDetails Story::readBranchDetails()
{
	Byte b1 = readNextByte();

	// If bit 7 is 0 the condition must be false, if 1 then the condition must be true
	bool comparisonValue = (b1 & 128) ? true : false;

	Word offset = (b1 & 63);

	// If bit 6 is set then the branch is 1 byte, otherwise it's 2
	if((b1 & 64) == 0)
	{
		auto b2 = readNextByte();
		offset = ((offset << 8 ) | b2);

		// We've got a signed 14 bit number. We need to sign extend it to 16 bits if bit 14 is set
		if(offset & 8192)
		{
			offset |= 49152;
		}
	}

	return BranchDetails(AsSignedWord(offset), comparisonValue);
}
Пример #4
0
void Story::callRoutine(Address routineAddress, Word returnVariable, const std::vector<Word> &arguments)
{
	// NOTE: special case! A call to address 0 means return false!
	if(routineAddress == 0)
	{
		returnFromCall(0);
		return; // NOTE: Early return
	}

	Address returnAddress = m_PC;

	auto normalizedAddress = expandPackedRoutineAddress(routineAddress);

	// Point to the new routine
	setPC(normalizedAddress);

	auto numberOfLocals = readNextByte();
	auto stackFrame = allocateNewFrame(returnAddress, arguments.size(), numberOfLocals, returnVariable);

	// The local default values are stored next
	if(m_Version <= 4)
	{
		// The defaults are next
		for(Byte i = 0; i < numberOfLocals; i++)
		{
			auto value = readNextWord();
			storeVariable(i + 1, value);
		}
	}
	else
	{
		// They all default to 0
		for(Byte i = 0; i < numberOfLocals; i++)
		{
			storeVariable(i + 1, 0);
		}
	}

	// Now layer the arguments on top
	auto argumentsToCopy = std::min(numberOfLocals, static_cast<Byte>(arguments.size()));
	for(Byte i = 0; i < argumentsToCopy; i++)
	{
		storeVariable(i + 1, arguments[i]);
	}

}
Пример #5
0
//FIXME: void announcePacket(uint16_t packetSize) {
void announcePacket()
{
	uint8_t buffer[ANNOUNCE_DATA_SIZE];
	uint16_t packetLength;

	// Transfer entire packet to RAM
	uint8_t* bufPtr = buffer;
	uint16_t count;

	readPointer = spiReadWord(REG_S2_RX_RD0) + S2_RX_START;

	// Read destination IP address
	for(count = 0; count < 4; count++) {
		spiWriteReg(REG_S2_DIPR0 + count, readNextByte());
	}

	// Read destination port - but ignore it and respond on 5555 anyway.
	readNextByte();
	readNextByte();
	spiWriteWord(REG_S2_DPORT0, ANNOUNCE_PORT);

	// Read packet length
	packetLength = readNextByte() | (readNextByte() << 8);

	// Trim overlong packets
	if(packetLength > ANNOUNCE_DATA_SIZE) packetLength = ANNOUNCE_DATA_SIZE;
	for(count = packetLength; --count;) {
		*bufPtr++ = readNextByte();
	}
	spiWriteWord(REG_S2_RX_RD0, readPointer - S2_RX_START); // Write back new pointer
	spiWriteWord(REG_S2_CR, CR_RECV); // Receive again

	// Dump packet
	bufPtr = buffer;

	// Parse packet
	if(memcmp(buffer, "arduino", 7) == 0) announceReply();
}
Пример #6
0
void i2cCheckPort(i2cPortData *pPort)
{
    switch(pPort->i2cState)
    {
        case I2C_STATE_START:
            if(!pPort->pConBits->SEN)
            {   // start done - send a read or write address
                sendAddress(pPort);
            }
            break;

        case I2C_STATE_ADDR:
            if(!pPort->pStatBits->TRSTAT)
            {   // address send done - did the device ack?
                if(!pPort->pStatBits->ACKSTAT)
                {   // device ack'd
                    if(pPort->writeSize)
                    {   // start writing
                        writeNextByte(pPort);
                    }
                    else
                    {   // start reading
                        readNextByte(pPort);
                    }
                }
                else
                {   // no ack - do a stop and give up
                    noAck(pPort);
                }
            }
            break;

        case I2C_STATE_WRITE:
            if(!pPort->pStatBits->TRSTAT)
            {   // write done - did the device ack?
                if(!pPort->pStatBits->ACKSTAT)
                { 
                    if(pPort->i2cIndex < pPort->writeSize)
                    {
                        writeNextByte(pPort);
                    }
                    else
                    {   // done writing - might need to read
                        if(pPort->readSize)
                        {   // repeat start
                            pPort->pConBits->RSEN = 1;
                            pPort->i2cState = I2C_STATE_R_START;
                        }
                        else
                        {
                            i2cStop(pPort);
                        }
                    }
                }
                else
                {
                    noAck(pPort);
                }
            }
            break;

        case I2C_STATE_R_START:
            if(!pPort->pConBits->RSEN)
            {   // Repeat start done - back to the address
                pPort->writeSize = 0;  // force a read
                sendAddress(pPort);
            }
            break;

        case I2C_STATE_READ:
            if(!pPort->pConBits->RCEN)
            {   // done reading, now do ack
                pPort->readBuffer[pPort->i2cIndex] = *pPort->pRxReg;
                pPort->i2cIndex++;
                pPort->pConBits->ACKDT = (pPort->i2cIndex == pPort->readSize);    // NACK on last byte
                pPort->pConBits->ACKEN = 1;
                pPort->i2cState = I2C_STATE_READ_ACK;
            }
            break;

        case I2C_STATE_READ_ACK:
            if(!pPort->pConBits->ACKEN)
            {   // done read ack
                if(pPort->i2cIndex >= pPort->readSize)
                {   // done receiving
                    i2cStop(pPort);
                }
                else
                {
                    readNextByte(pPort);
                }
            }
            break;

        case I2C_STATE_STOP:
            if(!pPort->pConBits->PEN)
            {   // stop condition done
                pPort->i2cState = I2C_STATE_IDLE;
                *pPort->pConReg  = I2CCON_OFF;       // Turn off the I2C
            }
            break;

        default:
            pPort->i2cState = I2C_STATE_IDLE;
            break;
    }
}