ssi_lm3s.c
Go to the documentation of this file.00001
00039 #include "ssi_lm3s.h"
00040
00041 #include <cfg/compiler.h>
00042 #include <cfg/debug.h>
00043
00044 #include <string.h>
00045
00046
00047 struct SSIClock
00048 {
00049 unsigned int cpsdvsr;
00050 unsigned int scr;
00051 };
00052
00053
00054
00055
00056 INLINE struct SSIClock
00057 lm3s_ssiPrescale(unsigned int bitrate)
00058 {
00059 struct SSIClock ret;
00060
00061 for (ret.cpsdvsr = 2, ret.scr = CPU_FREQ / bitrate / ret.cpsdvsr - 1;
00062 ret.scr > 255; ret.cpsdvsr += 2);
00063 ASSERT(ret.cpsdvsr < 255);
00064
00065 return ret;
00066 }
00067
00068
00069
00070
00071
00072
00073 int lm3s_ssiOpen(uint32_t addr, uint32_t frame, int mode,
00074 int bitrate, uint32_t data_width)
00075 {
00076 struct SSIClock ssi_clock;
00077
00078 ASSERT(addr == SSI0_BASE || addr == SSI1_BASE);
00079
00080 switch (mode)
00081 {
00082
00083 case SSI_MODE_SLAVE_OD:
00084 HWREG(addr + SSI_O_CR1) = SSI_CR1_SOD;
00085 break;
00086
00087 case SSI_MODE_SLAVE:
00088 HWREG(addr + SSI_O_CR1) = SSI_CR1_MS;
00089 break;
00090
00091 case SSI_MODE_MASTER:
00092 HWREG(addr + SSI_O_CR1) = 0;
00093 break;
00094 default:
00095 ASSERT(0);
00096 return -1;
00097 }
00098
00099 ssi_clock = lm3s_ssiPrescale(bitrate);
00100 HWREG(addr + SSI_O_CPSR) = ssi_clock.cpsdvsr;
00101 HWREG(addr + SSI_O_CR0) =
00102 (ssi_clock.scr << 8) |
00103 ((frame & 3) << 6) |
00104 (frame & SSI_CR0_FRF_M) |
00105 (data_width - 1);
00106
00107 HWREG(addr + SSI_O_CR1) |= SSI_CR1_SSE;
00108
00109 return 0;
00110 }
00111
00112
00113
00114
00115
00116
00117 static size_t lm3s_ssiWrite(struct KFile *fd, const void *buf, size_t size)
00118 {
00119 LM3SSSI *fds = LM3SSSI_CAST(fd);
00120 const char *p = (const char *)buf;
00121 uint32_t frame;
00122 size_t count = 0;
00123
00124 while (count < size)
00125 {
00126 frame = p[count];
00127 if (fds->flags & LM3S_SSI_NONBLOCK)
00128 {
00129 if (!lm3s_ssiWriteFrameNonBlocking(fds->addr,
00130 frame))
00131 break;
00132 }
00133 else
00134 lm3s_ssiWriteFrame(fds->addr, frame);
00135 count++;
00136 }
00137 return count;
00138 }
00139
00140
00141
00142
00143
00144
00145 static size_t lm3s_ssiRead(struct KFile *fd, void *buf, size_t size)
00146 {
00147 LM3SSSI *fds = LM3SSSI_CAST(fd);
00148
00149 uint8_t *p = (uint8_t *)buf;
00150 uint32_t frame;
00151 size_t count = 0;
00152
00153 while (count < size)
00154 {
00155 if (fds->flags & LM3S_SSI_NONBLOCK)
00156 {
00157 if (!lm3s_ssiReadFrameNonBlocking(fds->addr, &frame))
00158 break;
00159 }
00160 else
00161 lm3s_ssiReadFrame(fds->addr, &frame);
00162 *p++ = (uint8_t)frame;
00163 count++;
00164 }
00165 return count;
00166 }
00167
00168
00169
00170 static int lm3s_ssiFlush(struct KFile *fd)
00171 {
00172 LM3SSSI *fds = LM3SSSI_CAST(fd);
00173
00174 while (!lm3s_ssiTxDone(fds->addr))
00175 cpu_relax();
00176 return 0;
00177 }
00178
00179
00180 static int lm3s_ssiClose(struct KFile *fd)
00181 {
00182 LM3SSSI *fds = LM3SSSI_CAST(fd);
00183
00184 lm3s_ssiFlush(fd);
00185 HWREG(fds->addr + SSI_O_CR1) &= ~SSI_CR1_SSE;
00186 return 0;
00187 }
00188
00192 void lm3s_ssiInit(struct LM3SSSI *fds, uint32_t addr, uint32_t frame, int mode,
00193 int bitrate, uint32_t data_width)
00194 {
00195 memset(fds, 0, sizeof(*fds));
00196 DB(fds->fd._type = KFT_LM3SSSI);
00197
00198
00199 ASSERT(data_width == 8);
00200
00201 fds->fd.write = lm3s_ssiWrite;
00202 fds->fd.read = lm3s_ssiRead;
00203 fds->fd.close = lm3s_ssiClose;
00204 fds->fd.flush = lm3s_ssiFlush;
00205
00206 fds->addr = addr;
00207 lm3s_ssiOpen(addr, frame, mode, bitrate, data_width);
00208 }