uint8_t mcp2515_get_filter(uint8_t number, can_filter_t *filter)
{
	uint8_t mask_address;
	uint8_t filter_address;
	uint8_t temp;
	uint8_t mode = mcp2515_read_register(CANSTAT);
	
	if (number > 5)
		return 0;
	
	// change to configuration mode
	mcp2515_change_operation_mode( (1<<REQOP2) );
	
	if (number <= 1)
	{
		mask_address = RXM0SIDH;
		temp = mcp2515_read_register(RXB0CTRL);
	}
	else
	{
		mask_address = RXM1SIDH;
		temp = mcp2515_read_register(RXB1CTRL);
	}
	
	temp &= (1<<RXM1)|(1<<RXM0);
	
	if (temp == 0) {
		// filter and masks are disabled
		#if SUPPORT_EXTENDED_CANID
		filter->flags.extended = 0;
		#endif
		filter->flags.rtr = 0;
		filter->mask = 0;
		filter->id = 0;
		
		return 1;
	}
	
	#if SUPPORT_EXTENDED_CANID
	// transform bits so that they match the format from can.h
	temp >>= 5;
	temp = ~temp;
	if (temp & 1) temp = 0x3;
	
	filter->flags.extended = temp;
	#endif
	
	// read mask
	RESET(MCP2515_CS);
	spi_putc(SPI_READ);
	spi_putc(mask_address);
	mcp2515_read_id(&filter->mask);
	SET(MCP2515_CS);
	
	if (number <= 2)
	{
		filter_address = RXF0SIDH + number * 4;
	}
	else
	{
		filter_address = RXF3SIDH + (number - 3) * 4;
	}
	
	// read filter
	RESET(MCP2515_CS);
	spi_putc(SPI_READ);
	spi_putc(filter_address);
	mcp2515_read_id(&filter->id);
	SET(MCP2515_CS);
	
	// restore previous mode
	mcp2515_change_operation_mode( mode );
	
	return 1;
}
uint8_t mcp2515_get_message(can_t *msg)
{
    uint8_t addr;

    #ifdef  RXnBF_FUNKTION
        if (!IS_SET(MCP2515_RX0BF))
            addr = SPI_READ_RX;
        else if (!IS_SET(MCP2515_RX1BF))
            addr = SPI_READ_RX | 0x04;
        else
            return 0;
    #else
        // read status
        uint8_t status = mcp2515_read_status(SPI_RX_STATUS);

        if (_bit_is_set(status,6)) {
            // message in buffer 0
            addr = SPI_READ_RX;
        }
        else if (_bit_is_set(status,7)) {
            // message in buffer 1
            addr = SPI_READ_RX | 0x04;
        }
        else {
            // Error: no message available
            return 0;
        }
    #endif

    RESET(MCP2515_CS);
    spi_putc(addr);

    // CAN ID auslesen und ueberpruefen
    uint8_t tmp = mcp2515_read_id(&msg->id);
    #if SUPPORT_EXTENDED_CANID
        msg->flags.extended = tmp & 0x01;
    #else
        if (tmp & 0x01) {
            // Nachrichten mit extended ID verwerfen
            SET(MCP2515_CS);
            #ifdef  RXnBF_FUNKTION
            if (!IS_SET(MCP2515_RX0BF))
            #else
            if (_bit_is_set(status, 6))
            #endif
                mcp2515_bit_modify(CANINTF, (1<<RX0IF), 0);
            else
                mcp2515_bit_modify(CANINTF, (1<<RX1IF), 0);

            return 0;
        }
    #endif

    // read DLC
    uint8_t length = spi_putc(0xff);
    #ifdef RXnBF_FUNKTION
        if (!(tmp & 0x01))
            msg->flags.rtr = (tmp & 0x02) ? 1 : 0;
        else
            msg->flags.rtr = (length & (1<<RTR)) ? 1 : 0;
    #else
        msg->flags.rtr = (_bit_is_set(status, 3)) ? 1 : 0;
    #endif

    length &= 0x0f;
    msg->length = length;
    // read data
    for (uint8_t i=0;i<length;i++) {
        msg->data[i] = spi_putc(0xff);
    }
    SET(MCP2515_CS);

    // clear interrupt flag
    #ifdef RXnBF_FUNKTION
    if (!IS_SET(MCP2515_RX0BF))
    #else
    if (_bit_is_set(status, 6))
    #endif
        mcp2515_bit_modify(CANINTF, (1<<RX0IF), 0);
    else
        mcp2515_bit_modify(CANINTF, (1<<RX1IF), 0);

    CAN_INDICATE_RX_TRAFFIC_FUNCTION;

    #ifdef RXnBF_FUNKTION
        return 1;
    #else
        return (status & 0x07) + 1;
    #endif
}