/**
 * Request a few bytes from two wire slave device. Make slave device
 * NACK his address. Test if TwoWirePlus_bytesToReceive is set to 0 and no bytes are
 * received.
 */
static void TwoWirePlus_BaseTest_MasterReceiver_TC2(void)
{
	TwoWirePlus_BaseTest_resetBuffer();

	/* Start reading from address 0x42 four bytes */
	Wire.beginReception(0x42);
	Wire.requestBytes(4);
	/* Test if address SLA+R was written to txRingBuffer and that START was requested in TWCR */
	TEST_ASSERT_EQUAL_INT(TWOWIREPLUS_LASTOPERATION_WRITE, TwoWirePlus_txRingBuffer.lastOperation);
	TEST_ASSERT_EQUAL_INT(((0x42 << 1) | 0x01), TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_BaseTest_previousElement(TwoWirePlus_txRingBuffer.head)]);
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_TWCR_START), TWCR);
	/* Emulate START was generated */
	TWSR = TW_START;
	TWI_vect();
	/* Check if global TwoWirePlus_status was set correctly to START */
	TEST_ASSERT_EQUAL_INT((TW_START), TwoWirePlus_status);
	/* Preset TwoWirePlus_status register to emulate ACK for address from two wire slave device */
	TWSR = TW_MR_SLA_NACK;
	TWI_vect();
	/* Test if TwoWirePlus_status is set correctly and SLA+R was read from txRingBuffer and written to tw data register */
	TEST_ASSERT_EQUAL_INT((TW_MR_SLA_NACK), TwoWirePlus_status);
	TEST_ASSERT_EQUAL_INT(TWOWIREPLUS_LASTOPERATION_READ, TwoWirePlus_txRingBuffer.lastOperation);
	TEST_ASSERT_EQUAL_INT(((0x42 << 1) | 0x01), TWDR);
	/* Test if txRingBuffer is empty now because address was sent. */
	TEST_ASSERT(TwoWirePlus_RingBufferEmpty(TwoWirePlus_txRingBuffer));
	/* NACK was sent for address by two wire slave device, so no data to be received */
	TEST_ASSERT_EQUAL_INT(0x0, TwoWirePlus_bytesToReceive);
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWEA), TWCR);
	/* Wire.endReception can't be tested. A bit is set in this function and function will wait until bit is cleared in ISR */
}
/**
 * When ISR is called TwoWirePlus_status shall reflect the latest status of two
 * wire bus. Status is stored in bit 3 to 7 of TWSR.
 * Set different status values and test if status is copied to TwoWirePlus_status
 * and if only bit 3 to 7 are used.
 */
static void TwoWirePlus_BaseTest_ISR_TC1(void)
{
	TWSR = 0xaa;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((0xaa & 0xf8), TwoWirePlus_status);
	TWSR = 0x55;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((0x55 & 0xf8), TwoWirePlus_status);
}
/**
 * In case TW_MR_SLA_NACK was received fro m two wire slave device for SLA+R
 * no more bytes shall be received and therefore TwoWirePlus_bytesToReceive shall
 * be set to 0.
 * Set TwoWirePlus_bytesToReceive to some value and test if set to 0 in case of
 * TW_MR_SLA_NACK
 */
static void TwoWirePlus_BaseTest_ISR_TC2(void)
{
	TWSR = TW_MR_SLA_NACK;
	TwoWirePlus_bytesToReceive = 0xaa;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT(0, TwoWirePlus_bytesToReceive);
}
/**
 * In case of TW_MR_SLA_NACK, TW_MT_SLA_ACK, TW_MR_SLA_ACK, TW_MT_SLA_NACK, TW_MT_DATA_NACK
 * or TW_MT_DATA_ACK a byte was sent to two wire slave device earlier and therefore ring
 * buffer tail must be increased accordingly.
 * Set above mentioned two wire status, put one byte in txRingBuffer, call ISR and test if
 * byte was consumed in ISR.
 */
static void TwoWirePlus_BaseTest_ISR_TC3(void)
{
	TwoWirePlus_BaseTest_resetBuffer();
	TWSR = TW_MR_SLA_NACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0xaa;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT(TwoWirePlus_RingBufferEmpty(TwoWirePlus_txRingBuffer));

	TwoWirePlus_BaseTest_resetBuffer();
	TWSR = TW_MT_SLA_ACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0xaa;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT(TwoWirePlus_RingBufferEmpty(TwoWirePlus_txRingBuffer));

	TwoWirePlus_BaseTest_resetBuffer();
	TWSR = TW_MR_SLA_ACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0xaa;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT(TwoWirePlus_RingBufferEmpty(TwoWirePlus_txRingBuffer));

	TwoWirePlus_BaseTest_resetBuffer();
	TWSR = TW_MT_SLA_NACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0xaa;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT(TwoWirePlus_RingBufferEmpty(TwoWirePlus_txRingBuffer));

	TwoWirePlus_BaseTest_resetBuffer();
	TWSR = TW_MT_DATA_ACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0xaa;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT(TwoWirePlus_RingBufferEmpty(TwoWirePlus_txRingBuffer));
}
/**
 * Request a few bytes from two wire slave device. Make slave device
 * ACK his address. This test tests a typical two wire slave device
 * read.
 */
static void TwoWirePlus_BaseTest_MasterReceiver_TC1(void)
{
	TwoWirePlus_BaseTest_resetBuffer();

	/* Start reading from address 0x42 four bytes */
	Wire.beginReception(0x42);
	/* Test if address SLA+R was written to txRingBuffer and that START was requested in TWCR */
	TEST_ASSERT_EQUAL_INT(TWOWIREPLUS_LASTOPERATION_WRITE, TwoWirePlus_txRingBuffer.lastOperation);
	TEST_ASSERT_EQUAL_INT(((0x42 << 1) | 0x01), TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_BaseTest_previousElement(TwoWirePlus_txRingBuffer.head)]);
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_TWCR_START), TWCR);
	/* Request four bytes and see if they are requested */
	Wire.requestBytes(4);
	TEST_ASSERT_EQUAL_INT(0x4, TwoWirePlus_bytesToReceive);
	/* Emulate START was generated */
	TWSR = TW_START;
	TWI_vect();
	/* Check if global TwoWirePlus_status was set correctly to START */
	TEST_ASSERT_EQUAL_INT((TW_START), TwoWirePlus_status);
	/* Preset TwoWirePlus_status register to emulate ACK for address from two wire slave device */
	TWSR = TW_MR_SLA_ACK;
	TWI_vect();
	/* Test if TwoWirePlus_status is set correctly and SLA+R was read from txRingBuffer and written to tw data register */
	TEST_ASSERT_EQUAL_INT((TW_MR_SLA_ACK), TwoWirePlus_status);
	TEST_ASSERT_EQUAL_INT(TWOWIREPLUS_LASTOPERATION_READ, TwoWirePlus_txRingBuffer.lastOperation);
	TEST_ASSERT_EQUAL_INT(((0x42 << 1) | 0x01), TWDR);
	/* Test if txRingBuffer is empty now because address was sent. */
	TEST_ASSERT(TwoWirePlus_RingBufferEmpty(TwoWirePlus_txRingBuffer));
	/* Check if  TWIE, TWEN, TWEA and TWINT were set in ISR. */
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWEA | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);
	/* Now signal three bytes to be received from two wire slave device. Test if TWCR is set
	 * correctly to make sure ACK and not NACK was sent. */
	TWSR = TW_MR_DATA_ACK;
	TWDR = 0xa1;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TW_MR_DATA_ACK), TwoWirePlus_status);
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWEA | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);
	TWDR = 0xa2;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWEA | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);
	TWDR = 0xa3;
	TWI_vect();
	/* For the very last by a NACK shall be sent TWEA = 0 */
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);
	/* Signal last byte and test if NACH (TWEA not set) is returned to two wire slave device */
	TWDR = 0xa4;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWEA ), TWCR);
	/* Test if we really received four bytes and if the values match */
	TEST_ASSERT_EQUAL_INT(4, Wire.available());
	TEST_ASSERT_EQUAL_INT(0xa1, Wire.read());
	TEST_ASSERT_EQUAL_INT(3, Wire.available());
	TEST_ASSERT_EQUAL_INT(0xa2, Wire.read());
	TEST_ASSERT_EQUAL_INT(2, Wire.available());
	TEST_ASSERT_EQUAL_INT(0xa3, Wire.read());
	TEST_ASSERT_EQUAL_INT(1, Wire.available());
	TEST_ASSERT_EQUAL_INT(0xa4, Wire.read());
	TEST_ASSERT_EQUAL_INT(0, Wire.available());
	/* Wire.endReception can't be tested. A bit is set in this function and function will wait until bit is cleared in ISR */
}
/**
 * In case of TW_MT_SLA_ACK, TW_MR_SLA_ACK, TW_MT_SLA_NACK, TW_MT_DATA_NACK,
 * TW_MT_DATA_ACK, TW_START or TW_REP_START and no data available in txRingBuffer but
 * TwoWirePlus_bytesToReceive is 1, so only one more byte to sent, TW_INT shall be cleared and NACH
 * requested to signal that last byte is now about to be received. For TW_MR_SLA_NACK
 * TwoWirePlus_bytesToReceive will be set to 0 in ISR (see following tests).
 * Set above mentioned two wire status, set TwoWirePlus_bytesToReceive to 2, call ISR and
 * test if TW_INT is set correctly in TWSR.For TW_MR_SLA_NACK, TW_MT_SLA_ACK, TW_MR_SLA_ACK,
 * TW_MT_SLA_NACK, TW_MT_DATA_NACK and TW_MT_DATA_ACK one byte must be present in txRingBuffer
 * (see previous test)
 */
static void TwoWirePlus_BaseTest_ISR_TC6(void)
{
	TwoWirePlus_BaseTest_resetBuffer();
	TwoWirePlus_bytesToReceive = 1;
	TWSR = TW_MT_SLA_ACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0x55;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);

	TwoWirePlus_BaseTest_resetBuffer();
	TwoWirePlus_bytesToReceive = 1;
	TWSR = TW_MR_SLA_ACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0x55;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);

	TwoWirePlus_BaseTest_resetBuffer();
	TwoWirePlus_bytesToReceive = 1;
	TWSR = TW_MT_SLA_NACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0x55;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);

	TwoWirePlus_BaseTest_resetBuffer();
	TwoWirePlus_bytesToReceive = 1;
	TWSR = TW_MT_DATA_ACK;
	TwoWirePlus_txRingBuffer.buffer[TwoWirePlus_txRingBuffer.head] = 0x55;
	TwoWirePlus_incrementIndex(TwoWirePlus_txRingBuffer.head);
	TwoWirePlus_txRingBuffer.lastOperation = TWOWIREPLUS_LASTOPERATION_WRITE;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);

	TwoWirePlus_BaseTest_resetBuffer();
	TwoWirePlus_bytesToReceive = 1;
	TWSR = TW_START;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);

	TwoWirePlus_BaseTest_resetBuffer();
	TwoWirePlus_bytesToReceive = 1;
	TWSR = TW_REP_START;
	TWI_vect();
	TEST_ASSERT_EQUAL_INT((TWOWIREPLUS_BASETEST_TWCR_TWIE | TWOWIREPLUS_BASETEST_TWCR_TWEN | TWOWIREPLUS_BASETEST_TWCR_TWINT), TWCR);
}
Example #7
0
void sim_check_interrupts()
{
    unsigned int ticks = SDL_GetTicks();
    int tickDiff = ticks - prevTicks;
    prevTicks = ticks;
    
    if (!(SREG & _BV(SREG_I)))
        return;

#ifdef ENABLE_ULTILCD2
    if ((TWCR & _BV(TWEN)) && (TWCR & _BV(TWINT)) && (TWCR & _BV(TWIE)))
    {
        //Relay the TWI interrupt by 25ms one time till it gets disabled again. This fakes the LCD refresh rate.
        if (twiIntStart == 0)
            twiIntStart = SDL_GetTicks();
        if (SDL_GetTicks() - twiIntStart > 25)
        {
            cli();
            TWI_vect();
            _sei();
        }
    }
    if (!(TWCR & _BV(TWEN)) || !(TWCR & _BV(TWIE)))
    {
        twiIntStart = 0;
    }
#endif
    
    //if (tickDiff > 1)
    //    printf("Ticks slow! %i\n", tickDiff);
    if (tickDiff > 0)
    {
        ms_callback();
    
        cli();
        for(int n=0;n<tickDiff;n++)
        {
            if (TIMSK0 & _BV(OCIE0B))
                TIMER0_COMPB_vect();
            if (TIMSK0 & _BV(TOIE0))
                TIMER0_OVF_vect();
        }
        
        //Timer1 runs at 16Mhz / 8 ticks per second.
        unsigned int waveformMode = ((TCCR1B & (_BV(WGM13) | _BV(WGM12))) >> 1) | (TCCR1A & (_BV(WGM11) | _BV(WGM10)));
        unsigned int clockSource = TCCR1B & (_BV(CS12) | _BV(CS11) | _BV(CS10));
        unsigned int tickCount = F_CPU * tickDiff / 1000;
        unsigned int ticks = TCNT1;
        switch(clockSource)
        {
        case 0: tickCount = 0; break;
        case 1: break;
        case 2: tickCount /= 8; break;
        case 3: tickCount /= 64; break;
        case 4: tickCount /= 256; break;
        case 5: tickCount /= 1024; break;
        case 6: tickCount = 0; break;
        case 7: tickCount = 0; break;
        }
        tickCount *= 4;//For some reason the stepper speed is to slow, so cheat the timer routine.
        
        if (tickCount > 0 && OCR1A > 0)
        {
            ticks += tickCount;
            while(ticks > int(OCR1A))
            {
                ticks -= int(OCR1A);
                if (TIMSK1 & _BV(OCIE1A))
                    TIMER1_COMPA_vect();
            }
            TCNT1 = ticks;
        }
        _sei();
    }