#include #include #include #include /* SPI framework. * * currently alpha, uses interrupts, single master/single slave operation */ uint8_t * volatile spi_writeptr; uint8_t * volatile spi_readptr; uint8_t volatile spi_writelen; uint8_t volatile spi_readlen; uint8_t spi_readbuf[SPI_READBUF_LEN]; void spi_init(){ uint8_t spcr, spsr, d; /* calculate clock divisor, * gcc with optimize will do that calculation compile-time. */ uint8_t spi_clock_divisor(){ double d; d = F_CPU / SPI_BAUDRATE; d = ceil((log(d)/log(2))*0.95); // clock needs dividing by 2^d // the 0.95 to avoid ceil issues return d-1; // the -1 because minimum divisor is /2 } d = spi_clock_divisor(); if(d>7){ #warning "spi baudrate too slow, cannot be set" d=7; } //DDRs setzen #ifdef SPI_MASTER DDRB |= _BV(5) | _BV(3) | _BV(2); //MOSI, SCK, unused SS DDRB &= ~( _BV(4)); //MISO SPI_SSDDR |= _BV(SPI_SS_PIN); // actually used SS #else //SPI_MASTER DDRB |= _BV(4); //MISO DDRB &= ~( _BV(5) | _BV(3) | _BV(2)); //MOSI, SCK, SS #endif //SPI_MASTER spsr = 0; spsr |= (d & 1) ? 0 : _BV(SPI2X); spcr = 0 | _BV(SPE); spcr |= (d & 2) ? _BV(SPR0) : 0; spcr |= (d & 4) ? _BV(SPR1) : 0; #ifdef SPI_MASTER spcr |= _BV(MSTR); #endif SPSR = spsr; SPCR = spcr; } void spi_mst_start_packet(){ SPI_SSOUT &= ~(_BV(SPI_SS_PIN)); } void spi_mst_end_packet(){ SPI_SSOUT |= _BV(SPI_SS_PIN); } #define SPI_WAIT while(SPSR & _BV(SPIF)){;} void spi_mst_write(uint8_t len, uint8_t *data){ while(len>0){ SPDR = *data++; len--; SPI_WAIT; } } void spi_mst_read(uint8_t len, uint8_t *data){ while(len>0){ SPDR = 0; len--; SPI_WAIT; *data++ = SPDR; } } void spi_sla_handle_packet(){ uint8_t opcode, addr, do_write; uint16_t data; SPI_WAIT; SPDR = 0x53; // random ack SPI_WAIT; opcode = SPDR; do_write = spi_proto_needswrite(opcode); SPI_WAIT; addr = SPDR; SPDR = 0x00; // buys some pause if(do_write){ data = spi_proto_handlewrite(opcode, addr); SPI_WAIT; SPDR = data >> 8; SPI_WAIT; SPDR = data & 0xff; } else { SPI_WAIT; data = SPDR << 8; SPI_WAIT; data |= SPDR; spi_proto_handleread(opcode, addr, data); } } #ifndef SPI_MASTER ISR(SPI_vector){ } #endif //SPI_MASTER