spi.c 3.4 KB

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