/* * * mur.sat * * Somewhen in the year 2012, mur.at will have a nano satellite launched * into a low earth orbit (310 km above the surface of our planet). The * satellite itself is a TubeSat personal satellite kit, developed and * launched by interorbital systems. mur.sat is a joint venture of mur.at, * ESC im Labor and realraum. * * Please visit the project hompage at sat.mur.at for further information. * * * Copyright (C) 2012 Bernhard Tittelbach * * This file is part of mur.sat. * * mur.sat is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * mur.sat is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with mur.sat. If not, see . * */ #include #include #include "c1101lib.h" #include "spi.h" #include "usb_rawhid.h" #include "util.h" /**** Helper Functions ****/ #define SPIC1101_MAX_WAIT 21 int16_t spi_c1101_write_byte_ok_get_status(char data) { //~ uint8_t debug_sb[6]; char sb; unsigned int attempts = 0; do { sb = spi_exchange_byte(data); //Note: content of returned StatusByte is actually context depenedant on sent command // i.e. we won't get Fifo Byte count or overflow status on normal command and so on // e.g. we only get TX Fifo Free Byte count while writing to TX Fifo // thus it makes sense to only check for CHIP_RDY here //~ usb_rawhid_send((uint8_t*)"spi byte exchanged ",255); //~ debug_sprint_int16hex(debug_sb, sb); //~ usb_rawhid_send(debug_sb,255); if (attempts++ > SPIC1101_MAX_WAIT) return -1; } while ( SPIC1101_SB_CHIP_NOT_RDY(sb) ); return sb; } // note addresses range from 0x00 to 0x2F for normal registers and 0xF0 to 0xFD for special status registers int16_t spi_c1101_read_register(char address) { char rbyte; if (address < 0x30) address |= 0x80; else address |= 0xC0; spi_cs_enable(); spi_c1101_wait_chip_rdy(); if (spi_c1101_write_byte_ok_get_status(address) < 0) return -1; _delay_ms(10); //FIXME: propably don't need this rbyte = spi_read_byte(); spi_cs_disable(); return rbyte; } // note addresses range from 0x00 to 0x2F for normal registers int16_t spi_c1101_write_register(char address, char byte) { spi_cs_enable(); spi_c1101_wait_chip_rdy(); if (spi_c1101_write_byte_ok_get_status(address & 0x2F) < 0) return -1; _delay_ms(2); if (spi_c1101_write_byte_ok_get_status(byte) < 0) return -1; spi_cs_disable(); return 1; } // note addresses range from 0x30 to 0x3D for command strobes int16_t spi_c1101_strobe_command(char address) { if (spi_c1101_write_byte_ok_get_status(address) < 0) return -1; return 1; } int spi_c1101_read_rxfifo(int leave_num_bytes, char *buffer, int maxlen) { int16_t sb; int num_read = 0; int num_fifo_available = 0; spi_cs_enable(); spi_c1101_wait_chip_rdy(); sb = spi_c1101_write_byte_ok_get_status(SPIC1101_ADDR_FIFO_READ_BURST); if (sb < 0) return -1; num_fifo_available = SPIC1101_SB_FIFO_BYTES_AVAILABLE((char)sb); //note if num_fifo_available == 15 then 15 or more bytes are available //FIXTHIS while (maxlen-- && num_fifo_available - num_read <= leave_num_bytes) { //hope this works !! buffer[num_read++] = spi_read_byte(); } spi_cs_disable(); return num_read; } //note: always check if num_written returned == len given int spi_c1101_write_txfifo(char *buffer, int len) { char sb; int num_written = 0; int num_fifo_available = 0; spi_cs_enable(); spi_c1101_wait_chip_rdy(); sb = spi_c1101_write_byte_ok_get_status(SPIC1101_ADDR_FIFO_WRITE_BURST); if (sb < 0) return -1; num_fifo_available = SPIC1101_SB_FIFO_BYTES_AVAILABLE((char)sb); //note if num_fifo_available == 15 then 15 or more bytes are available //FIXTHIS if (num_fifo_available < len) len = num_fifo_available; while (len--) { //hope this works !! spi_write_byte(buffer[num_written++]); } spi_cs_disable(); return num_written; } /**** External Functions ****/ void c1101_init(void) { //reset C1101 spi_c1101_strobe_command(SPIC1101_ADDR_SRES); _delay_ms(100); //flush FIFOs spi_c1101_strobe_command(SPIC1101_ADDR_SFRX); spi_c1101_strobe_command(SPIC1101_ADDR_SFTX); c1101_getStatus(); } char c1101_getVersion(void) { return spi_c1101_read_register(SPIC1101_ADDR_VERSION); } char c1101_getPartNum(void) { return spi_c1101_read_register(SPIC1101_ADDR_PARTNUM); } void c1101_handleStatusByte(char sb) { //on RXFifo Overflow, Flush RX Fifo if (SPIC1101_SB_RXFIFO_OVERFLOW(sb)) { spi_c1101_strobe_command(SPIC1101_ADDR_SFRX); usb_rawhid_send((uint8_t*)"RX fifo flushed",255); } //on TXFifo Overflow, Flush TX Fifo if (SPIC1101_SB_TXFIFO_OVERFLOW(sb)) { spi_c1101_strobe_command(SPIC1101_ADDR_SFTX); usb_rawhid_send((uint8_t*)"TX fifo flushed",255); } } char c1101_getStatus(void) { char sb=0; spi_cs_enable(); spi_c1101_wait_chip_rdy(); sb = spi_c1101_write_byte_ok_get_status(SPIC1101_ADDR_SNOP); spi_cs_disable(); //debug start uint8_t debug_sb[6]; usb_rawhid_send((uint8_t*)"c1101 status:",255); debug_sprint_int16hex(debug_sb, sb); usb_rawhid_send(debug_sb,255); //debug end c1101_handleStatusByte(sb); return sb; } //max len: 64 bytes void c1101_writeTXFifo(char *buffer, unsigned int len) { //check TXBYTES.NUM_TXBYTES // never write more bytes than avaiblabe or doom ensues } //max returned: 64 bytes int c1101_readRXFifo(char *buffer) { //check RXBYTES.NUM_RXBYTES // never read more bytes than avaiblabe or we will read garbage //note: if RX transmission fills fifo buffer at exact same time as last RX Fifo Bit is read via SPI, Fifo Pointer will not be properly updated // and last read byte will be duplicated. // thus: don't last avialable FIFO Bytes unless we can be sure that it will be the last byte of a packet and we can be sure that a following duplicated byte is actually an Fifo duplication and not an actually recieved byte ! return 0; }