spi.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* sd2snes - SD card based universal cartridge for the SNES
  2. Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
  3. This file was adapted from sd2iec, written by Ingo Korb.
  4. Original copyright header follows:
  5. */
  6. /* sd2iec - SD/MMC to Commodore serial bus interface/controller
  7. Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
  8. Inspiration and low-level SD/MMC access based on code from MMC2IEC
  9. by Lars Pontoppidan et al., see sdcard.c|h and config.h.
  10. FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
  11. This program is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; version 2 of the License only.
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. GNU General Public License for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. spi.c: Low level SPI access
  22. Extended, optimized and cleaned version of code from MMC2IEC,
  23. original copyright header follows:
  24. //
  25. // Title : SPI module
  26. // Author : Lars Pontoppidan
  27. // Date : January, 2007
  28. // Version : 1.03
  29. // Target MCU : Atmel AVR Series
  30. //
  31. // DESCRIPTION:
  32. // This module implements initialization, sending and receiving bytes using
  33. // hardware SPI on an AVR.
  34. //
  35. // DISCLAIMER:
  36. // The author is in no way responsible for any problems or damage caused by
  37. // using this code. Use at your own risk.
  38. //
  39. // LICENSE:
  40. // This code is distributed under the GNU Public License
  41. // which can be found at http://www.gnu.org/licenses/gpl.txt
  42. //
  43. */
  44. // FIXME: Integrate into sdcard.c
  45. #include <avr/io.h>
  46. #include "avrcompat.h"
  47. #include "spi.h"
  48. // access routines
  49. void spiInit(void)
  50. {
  51. volatile uint8_t dummy;
  52. // setup SPI I/O pins
  53. SPI_PORT = (SPI_PORT & ~SPI_MASK) | SPI_SCK | SPI_SS | SPI_MISO;
  54. SPI_DDR = (SPI_DDR & ~SPI_MASK) | SPI_SCK | SPI_SS | SPI_MOSI;
  55. // setup SPI interface:
  56. // interrupts disabled, SPI enabled, MSB first, master mode,
  57. // leading edge rising, sample on leading edge, clock = f/4
  58. SPCR = 0b01010000;
  59. // Enable SPI double speed mode -> clock = f/2
  60. SPSR = _BV(SPI2X);
  61. // clear status
  62. dummy = SPSR;
  63. // clear receive buffer
  64. dummy = SPDR;
  65. }
  66. inline uint8_t spiTransferByte(uint8_t data)
  67. {
  68. // send the given data
  69. SPDR = data;
  70. // wait for transfer to complete
  71. loop_until_bit_is_set(SPSR, SPIF);
  72. // *** reading of the SPSR and SPDR are crucial
  73. // *** to the clearing of the SPIF flag
  74. // *** in non-interrupt mode
  75. // return the received data
  76. return SPDR;
  77. }
  78. inline uint32_t spiTransferLong(const uint32_t data)
  79. {
  80. // It seems to be necessary to use the union in order to get efficient
  81. // assembler code.
  82. // Beware, endian unsafe union
  83. union {
  84. uint32_t l;
  85. uint8_t c[4];
  86. } long2char;
  87. long2char.l = data;
  88. // send the given data
  89. SPDR = long2char.c[3];
  90. // wait for transfer to complete
  91. loop_until_bit_is_set(SPSR, SPIF);
  92. long2char.c[3] = SPDR;
  93. SPDR = long2char.c[2];
  94. // wait for transfer to complete
  95. loop_until_bit_is_set(SPSR, SPIF);
  96. long2char.c[2] = SPDR;
  97. SPDR = long2char.c[1];
  98. // wait for transfer to complete
  99. loop_until_bit_is_set(SPSR, SPIF);
  100. long2char.c[1] = SPDR;
  101. SPDR = long2char.c[0];
  102. // wait for transfer to complete
  103. loop_until_bit_is_set(SPSR, SPIF);
  104. long2char.c[0] = SPDR;
  105. return long2char.l;
  106. }