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