uart.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. uart.c: UART access routines
  22. */
  23. #include <avr/io.h>
  24. #include <avr/interrupt.h>
  25. #include <avr/pgmspace.h>
  26. #include <stdio.h>
  27. #include "config.h"
  28. #include "avrcompat.h"
  29. #include "uart.h"
  30. static uint8_t txbuf[1 << CONFIG_UART_BUF_SHIFT];
  31. static volatile uint16_t read_idx;
  32. static volatile uint16_t write_idx;
  33. ISR(USART_UDRE_vect) {
  34. if (read_idx == write_idx) return;
  35. UDR = txbuf[read_idx];
  36. read_idx = (read_idx+1) & (sizeof(txbuf)-1);
  37. if (read_idx == write_idx)
  38. UCSRB &= ~ _BV(UDRIE);
  39. }
  40. void uart_putc(char c) {
  41. uint16_t t=(write_idx+1) & (sizeof(txbuf)-1);
  42. #ifndef CONFIG_DEADLOCK_ME_HARDER // :-)
  43. UCSRB &= ~ _BV(UDRIE); // turn off RS232 irq
  44. #else
  45. while (t == read_idx); // wait for free space
  46. #endif
  47. txbuf[write_idx] = c;
  48. write_idx = t;
  49. //if (read_idx == write_idx) PORTD |= _BV(PD7);
  50. UCSRB |= _BV(UDRIE);
  51. }
  52. void uart_puthex(uint8_t num) {
  53. uint8_t tmp;
  54. tmp = (num & 0xf0) >> 4;
  55. if (tmp < 10)
  56. uart_putc('0'+tmp);
  57. else
  58. uart_putc('a'+tmp-10);
  59. tmp = num & 0x0f;
  60. if (tmp < 10)
  61. uart_putc('0'+tmp);
  62. else
  63. uart_putc('a'+tmp-10);
  64. }
  65. void uart_puthexlong(uint32_t num) {
  66. uart_puthex((num>>24)&0xff);
  67. uart_puthex((num>>16)&0xff);
  68. uart_puthex((num>>8)&0xff);
  69. uart_puthex(num&0xff);
  70. }
  71. void uart_puthexshort(uint16_t num) {
  72. uart_puthex((num>>8)&0xff);
  73. uart_puthex(num&0xff);
  74. }
  75. void uart_trace(void *ptr, uint16_t start, uint16_t len) {
  76. uint16_t i;
  77. uint8_t j;
  78. uint8_t ch;
  79. uint8_t *data = ptr;
  80. data+=start;
  81. for(i=0;i<len;i+=16) {
  82. uart_puthex(start>>8);
  83. uart_puthex(start&0xff);
  84. uart_putc('|');
  85. uart_putc(' ');
  86. for(j=0;j<16;j++) {
  87. if(i+j<len) {
  88. ch=*(data + j);
  89. uart_puthex(ch);
  90. } else {
  91. uart_putc(' ');
  92. uart_putc(' ');
  93. }
  94. uart_putc(' ');
  95. }
  96. uart_putc('|');
  97. for(j=0;j<16;j++) {
  98. if(i+j<len) {
  99. ch=*(data++);
  100. if(ch<32 || ch>0x7e)
  101. ch='.';
  102. uart_putc(ch);
  103. } else {
  104. uart_putc(' ');
  105. }
  106. }
  107. uart_putc('|');
  108. uart_putcrlf();
  109. start+=16;
  110. }
  111. }
  112. static int ioputc(char c, FILE *stream) {
  113. if (c == '\n') uart_putc('\r');
  114. uart_putc(c);
  115. return 0;
  116. }
  117. uint8_t uart_getc(void) {
  118. loop_until_bit_is_set(UCSRA,RXC);
  119. return UDR;
  120. }
  121. void uart_flush(void) {
  122. while (read_idx != write_idx) ;
  123. }
  124. void uart_puts_P(prog_char *text) {
  125. uint8_t ch;
  126. while ((ch = pgm_read_byte(text++))) {
  127. uart_putc(ch);
  128. }
  129. }
  130. void uart_putcrlf(void) {
  131. uart_putc(13);
  132. uart_putc(10);
  133. }
  134. static FILE mystdout = FDEV_SETUP_STREAM(ioputc, NULL, _FDEV_SETUP_WRITE);
  135. void uart_init(void) {
  136. /* Seriellen Port konfigurieren */
  137. /* UBRRH = (int)((double)F_CPU/(16.0*CONFIG_UART_BAUDRATE)-1) >> 8;
  138. UBRRL = (int)((double)F_CPU/(16.0*CONFIG_UART_BAUDRATE)-1) & 0xff;*/
  139. UBRRH = (int)((double)F_CPU/(8.0*CONFIG_UART_BAUDRATE)-1) >> 8;
  140. UBRRL = (int)((double)F_CPU/(8.0*CONFIG_UART_BAUDRATE)-1) & 0xff;
  141. UCSRA |= _BV(U2X0);
  142. UCSRB = _BV(RXEN) | _BV(TXEN);
  143. // I really don't like random #ifdefs in the code =(
  144. #if defined __AVR_ATmega32__
  145. UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
  146. #else
  147. UCSRC = _BV(UCSZ1) | _BV(UCSZ0);
  148. #endif
  149. stdout = &mystdout;
  150. //UCSRB |= _BV(UDRIE);
  151. read_idx = 0;
  152. write_idx = 0;
  153. }