00001 #include "ABBdaemon.h"
00002
00003 #include "mprace/ABB.h"
00004 #include "mprace/DMABuffer.h"
00005
00006 #include "abbdaemon/CTLpacket.h"
00007 #include "abbdaemon/CTLresponse.h"
00008
00009 #include <iostream>
00010
00011 using namespace std;
00012
00013
00014 #define DID (0x0000 >> 2)
00015 #define GSR (0x0020 >> 2)
00016 #define CTL_H2R (0x00A0 >> 2)
00017 #define CTL_R2H (0x00A0 >> 2)
00018 #define DLM_H2R (0x00A4 >> 2)
00019 #define DLM_R2H (0x00A4 >> 2)
00020 #define CTL_STATUS (0x00AC >> 2)
00021 #define CTL_CONTROL (0x00AC >> 2)
00022
00023 #define EVENT_BUFFER_STATUS (0x0090 >> 2)
00024
00025 #define CTL_PACKET_AVAIL (0x00000001)
00026 #define CTL_FIFO_RESET (0x0A)
00027 #define EVENT_BUFFER_RESET (0x0A)
00028 #define CTL_EOP (0x10000)
00029 #define CTL_SOP (0x20000)
00030 #define CTL_MASK (0x0000FFFF)
00031 #define DLM_VALID (0x00020000)
00032 #define DLM_MASK (0x0000000F)
00033
00034
00035
00036 abbdaemon::ABBdaemonClient::ABBdaemonClient(const char*, int role)
00037 {
00038 try {
00039 board = new mprace::ABB(0);
00040 } catch (...) {
00041 board = 0;
00042 std::cerr << "Could not create ABB board. Is the driver properly loaded?" << std::endl;
00043 }
00044
00045 debug = 0;
00046
00047 }
00048
00049 abbdaemon::ABBdaemonClient::~ABBdaemonClient()
00050 {
00051 delete board;
00052 board = 0;
00053 }
00054
00055 void abbdaemon::ABBdaemonClient::enableDebugMessages(bool enable)
00056 {
00057 debug = enable ? &std::cout : 0;
00058 }
00059
00060 uint32_t abbdaemon::ABBdaemonClient::submitReset(uint32_t what)
00061 {
00062 if (board==0) return 1;
00063
00064 if (debug) (*debug) << "Client wants to reset " << what << endl;
00065 if (what == RESET_ALL || what == RESET_CTL_FIFO) {
00066 if (debug) (*debug) << "Resetting CTL_FIFO" << endl;
00067 board->setReg(CTL_CONTROL, CTL_FIFO_RESET);
00068 }
00069
00070 if (what == RESET_ALL || what == RESET_ABB) {
00071 if (debug) (*debug) << "Resetting eventbuffer" << endl;
00072 board->setReg(EVENT_BUFFER_STATUS, EVENT_BUFFER_RESET);
00073 }
00074
00075 if (what == RESET_ALL || what == RESET_FIFO_TIMEOUT) {
00076 if (debug) (*debug) << "Resetting FIFO timeout flag" << endl;
00077 board->setReg(0x1E, 0x0A);
00078 }
00079
00080 if (debug) (*debug) << "After reset status is: "
00081 << hex << board->getReg(CTL_STATUS) << dec << endl;
00082
00083 if (debug) (*debug) << "General status register is: "
00084 << hex << board->getReg(GSR) << dec << endl;
00085
00086 return 0;
00087 }
00088
00089 uint32_t abbdaemon::ABBdaemonClient::submitNOper(uint32_t rocid, uint32_t retid, int t_number,
00090 uint32_t *addrs, uint32_t *values, uint32_t *retvals)
00091 {
00092 if (board==0) return 1;
00093
00094 uint32_t retcode = 0;
00095
00096
00097
00098 while ((t_number > 0) && (retcode==0)) {
00099
00100 CTLpacket packet(rocid, retid);
00101
00102 int number = t_number;
00103 if (number > 6) number = 6;
00104
00105 for (int i = 0; i < number; i++) {
00106 uint32_t addr = addrs[i];
00107
00108
00109
00110
00111 addr &= 0x7FFFFFFF;
00112 if (debug) (*debug) << i << " : " << addr << " = " << values[i] << endl;
00113
00114 if (addrs[i] & 0x80000000)
00115 packet.add(CTLcommand(PUT, addr, values[i]));
00116 else
00117 packet.add(CTLcommand(GET, addr));
00118 }
00119
00120 std::list<CTLresponse*> replies = packet.send(board);
00121
00122 if (replies.size()==0) retcode = 2;
00123
00124 std::list<CTLresponse*>::iterator iter = replies.begin();
00125 int i = 0;
00126
00127 while (iter!=replies.end()) {
00128
00129 CTLresponse* r = *iter++;
00130
00131 CTLpacket::CTLcmd expected = ((addrs[i] & 0x80000000) ?
00132 CTLpacket::ACKPUT :
00133 CTLpacket::ACKGET);
00134
00135 if (r->getCTLcmd() != expected) {
00136 retcode = 1;
00137 if (expected == CTLpacket::ACKGET)
00138 values[i] = -1;
00139 if (debug) (*debug) << "getCTLcmd = " << r->getCTLcmd() << ", expected = " << expected << endl;
00140 if (retvals) retvals[i] = -(r->getErrorCode());
00141 if (debug) (*debug) << "getErrorCode = " << r->getErrorCode() << ", value = " << -(r->getErrorCode()) << endl;
00142 } else {
00143 if (expected == CTLpacket::ACKGET)
00144 values[i] = r->getValue();
00145
00146 if (retvals) retvals[i] = 0;
00147 }
00148
00149 delete r;
00150 i++;
00151 }
00152 t_number -= number;
00153 addrs+=number;
00154 values+=number;
00155 retvals+=number;
00156
00157 }
00158
00159 return retcode;
00160 }
00161
00162 uint32_t abbdaemon::ABBdaemonClient::submitPut(uint32_t rocid, uint32_t retid, uint32_t addr, uint32_t value)
00163 {
00164 addr |= 0x80000000;
00165 return submitNOper(rocid, retid, 1, &addr, &value, 0);
00166 }
00167
00168 uint32_t abbdaemon::ABBdaemonClient::submitNPut(uint32_t rocid, uint32_t retid, int number,
00169 uint32_t *addrs, uint32_t *values, uint32_t *retvals)
00170 {
00171 for (int i=0;i<number;i++) addrs[i] |= 0x80000000;
00172
00173 uint32_t retcode = submitNOper(rocid, retid, number, addrs, values, retvals);
00174
00175 for (int i=0;i<number;i++) addrs[i] &= 0x7FFFFFFF;
00176
00177 return retcode;
00178 }
00179
00180 uint32_t abbdaemon::ABBdaemonClient::submitGet(uint32_t rocid, uint32_t retid, uint32_t addr, uint32_t *value)
00181 {
00182 return submitNOper(rocid, retid, 1, &addr, value, 0);
00183 }
00184
00185 uint32_t abbdaemon::ABBdaemonClient::submitNGet(uint32_t rocid, uint32_t retid, int number,
00186 uint32_t *addrs, uint32_t *values, uint32_t *retvals)
00187 {
00188 return submitNOper(rocid, retid, number, addrs, values, retvals);
00189 }
00190
00191 uint32_t abbdaemon::ABBdaemonClient::submitPutDLM(uint32_t value)
00192 {
00193 if (board==0) return 1;
00194 if (debug) (*debug) << "Requested DLM put with value: " << value << endl;
00195
00196 try {
00197 board->setReg(DLM_H2R, (value & DLM_MASK) );
00198 } catch (mprace::Exception &e) {
00199 return 1;
00200 }
00201
00202 return 0;
00203 }
00204
00205 uint32_t abbdaemon::ABBdaemonClient::submitGetDLM(uint32_t *retvalue)
00206 {
00207 if (board==0) return 1;
00208
00209 try {
00210 volatile unsigned int valid;
00211 unsigned int value;
00212
00213 if (debug) (*debug) << "Waiting for incoming data: " << flush;
00214
00215 do {
00216 value = board->getReg(DLM_R2H);
00217 valid = (value & DLM_VALID);
00218 if (debug) (*debug) << "." << flush;
00219 } while (valid == 0);
00220
00221 if (debug) (*debug) << " got a DLM!" << endl;
00222 if (debug) (*debug) << "Got DLM message: " << hex << value << dec << endl;
00223
00224 if (retvalue) *retvalue = (value & DLM_MASK);
00225 } catch (mprace::Exception &e) {
00226 return 1;
00227 }
00228
00229 return 0;
00230 }
00231
00232 uint32_t abbdaemon::ABBdaemonClient::readDMAserialized(const unsigned int address,
00233 DMABUFFER_HANDLE buffer_handle, const unsigned int count,
00234 const unsigned int offset, const bool inc,
00235 const bool lock, const float timeout)
00236 {
00237 if (board==0) return 1;
00238
00239 try {
00240 board->readDMAFIFO(address, *reinterpret_cast<mprace::DMABuffer*>(buffer_handle), count, offset, inc, lock, timeout);
00241 if (debug) (*debug) << "FIFO status: " << hex << board->getReg(0x24) << dec << endl;
00242
00243 } catch (mprace::Exception &e) {
00244 cerr << "Something failed" << endl;
00245 return 1;
00246 }
00247
00248 return 0;
00249 }
00250
00251 abbdaemon::DMABUFFER_HANDLE abbdaemon::ABBdaemonClient::registerBuffer(unsigned int len, void *address)
00252 {
00253 if (debug) (*debug) << "Registering buffer at " << address << " of size " << len << endl;
00254
00255 mprace::DMABuffer *buffer = new mprace::DMABuffer(*board, len, (unsigned int*)address);
00256
00257 return (DMABUFFER_HANDLE) buffer;
00258 }
00259
00260 void abbdaemon::ABBdaemonClient::syncBuffer(DMABUFFER_HANDLE buffer)
00261 {
00262 if (buffer)
00263 (reinterpret_cast<mprace::DMABuffer*>(buffer))->sync(mprace::DMABuffer::FROMDEVICE);
00264
00265 }
00266
00267 void abbdaemon::ABBdaemonClient::unregisterBuffer(DMABUFFER_HANDLE buffer)
00268 {
00269 if (debug) (*debug) << "Unregistering buffer at " << buffer << endl;
00270
00271 if (buffer)
00272 delete reinterpret_cast<mprace::DMABuffer*>(buffer);
00273 }
00274
00275 uint32_t abbdaemon::ABBdaemonClient::getFIFOStatus()
00276 {
00277 if (board==0) return 0;
00278
00279
00280 return board->getReg(EVENT_BUFFER_STATUS) & 0xFFFFFFF8;
00281 }
00282
00283 uint32_t abbdaemon::ABBdaemonClient::getCTLStatus()
00284 {
00285 if (board==0) return 0;
00286
00287 return board->getReg(CTL_STATUS);
00288 }
00289
00290 void abbdaemon::ABBdaemonClient::getDesignID(uint32_t *version, uint32_t *major, uint32_t *author, uint32_t *minor)
00291 {
00292 if (board==0) return;
00293
00294 uint32_t id = board->getReg(DID);
00295
00296 if (version) *version = (id & 0xFF000000) >> 24;
00297 if (major) *major = (id & 0x00FF0000) >> 16;
00298 if (author) *author = (id & 0x0000F000) >> 12;
00299 if (minor) *minor = (id & 0x00000FFF);
00300 }
00301
00302 void abbdaemon::ABBdaemonClient::setReg(uint32_t reg, uint32_t value)
00303 {
00304 if (board) board->setReg(reg, value);
00305
00306 }