class library to access fischertechnik interfaces via USB
Dependencies: FatFileSystem mbed myBlueUSB neigbourhood rfcomm sdp
ftlib/ftlibclasstxc.cpp
- Committer:
- networker
- Date:
- 2013-03-11
- Revision:
- 1:4676e8b9b357
- Parent:
- 0:7da612835693
File content as of revision 1:4676e8b9b357:
#include "mbed.h" #include "USBHost.h" #include "ftlibclasstxc.h" #include "ftErrCode.h" ftusbdevtx::ftusbdevtx(): ftusbdev(0, FT_TXC, 0) { sid = 0; tid = 0; active = 0; transferAktiv = FTX1STOP; cbRoboExtState = 0; for (int i = TA_LOCAL; i < TA_N_PARTS; i++) ta[i] = 0; } ftusbdevtx::ftusbdevtx(int d): ftusbdev(d, FT_TXC, 0) { sid = 0; tid = 0; active = 0; transferAktiv = FTX1STOP; cbRoboExtState = 0; for (int i = TA_LOCAL; i < TA_N_PARTS; i++) ta[i] = 0; set_baudrate(38400); send_msg(1); //ping GetFtSerialNr(); } void ftusbdevtx::getSlaveInfo() { send_msg(7, 1); //get state for master for (int i = 1; i <= N_EXT_DEV; i++) if (ta[0]->state.ext_dev_connect_state[i-1]) { if (ta[i] == 0) { //new slave ta[i] = new TA; memset(ta[i], 0, sizeof(TA)); active |= 1<<i; send_msg(6, 1<<i); //get info for slave; printf("New Extension %d = %s\n", i, ta[i]->info.device_name); if (cbRoboExtState) cbRoboExtState(i, 1); } } else { if (ta[i]) { delete ta[i]; ta[i] = 0; active &= ~(1<<i); printf("Extension %d went offline\n", i); if (cbRoboExtState) cbRoboExtState(i, 0); } } // send_msg(6, active & ~1); //get info for slaves; } unsigned ftusbdevtx::OpenFtUsbDevice() { ta[0] = new TA; memset(ta[0], 0, sizeof(TA)); active = 1; send_msg(6, 1); //get info for master printf("Master=%s\n", ta[0]->info.device_name); getSlaveInfo(); /* send_msg(7, 1); //get state for master for (int i = 0; i < N_EXT_DEV; i++) if (ta[0]->state.ext_dev_connect_state[i]) { ta[i+1] = new TA; memset(ta[i+1], 0, sizeof(TA)); active |= 1<<(i+1); send_msg(6, 1<<(i+1)); //get info for slave; printf("Extension %d = %s\n", i+1, ta[i+1]->info.device_name); }*/ // send_msg(6, active & ~1); //get info for slaves; return 0; } unsigned ftusbdevtx::CloseFtDevice() { if (ta[0]==0) return FTLIB_ERR_DEVICE_NOT_OPEN; while (transferAktiv != FTX1STOP) { fprintf(stderr, "Transfer ta still active\n"); wait(1); } for (int i = 0; i < N_EXT_DEV; i++) if (ta[i]!=0) { delete ta[i]; ta[i] = 0; } return 0; } unsigned ftusbdevtx::IsFtTransferActiv() { if (ta[0] == 0) return FTLIB_ERR_DEVICE_NOT_OPEN;//or just say not running if (transferAktiv == FTX1RUN) return FTLIB_ERR_THREAD_IS_RUNNING; if (transferAktiv == FTX1STOP) return FTLIB_ERR_THREAD_NOT_RUNNING; return FTLIB_ERR_THREAD_SYNCHRONIZED; } unsigned ftusbdevtx::set_baudrate(unsigned br) { unsigned char buffer[7] = {0x00, 0x96, 0x00, 0x00, 0, 0, 8}; *(unsigned*)buffer = br; int ret = USBControlTransfer(device, 0x21, 0x20, 0, 0, buffer, 7); if (ret != 7) printf("error setting Baudrate: %d\n", ret); ret = USBControlTransfer(device, 0xa1, 0x21, 0, 0, buffer, 7); if (ret == 7) printf("baudrate=%d, format=%d, parity=%d, bits=%d\n", *(int*)buffer, buffer[4], buffer[5], buffer[6]); else printf("error getting Baudrate: %d\n", ret); return *(unsigned*)buffer; } unsigned ftusbdevtx::GetFtSerialNr() { if (sn) return sn; unsigned char req_sn[] = "\x0dget_ser_num\x0d"; char ser[80]; memset(ser, 0, sizeof(ser)); int ret=write_data(req_sn, sizeof(req_sn)-1); if (ret != sizeof(req_sn)-1) printf("bulk write error: %d\n", ret); ret=read_data((unsigned char*)ser, sizeof(ser)); if (ret < 0) printf("bulk read error: %d\n", ret); char s1[41],s3[31]; unsigned num=0; int n = sscanf(ser,"\x0d\x0a%40[^\n\r]%u\x0d\x0a%30[^\n\r]", s1, &num, s3); if (n==3) { sn = num; printf("%010u %s\n", num, s3); } else printf("could not parse serial number [%s]\n", ser); return sn; } char* ftusbdevtx::GetFtLongNameStrg() { unsigned char req_sn[] = "\x0dget_ser_num\x0d"; char ser[80]; memset(ser, 0, sizeof(ser)); int ret=write_data(req_sn, sizeof(req_sn)-1); if (ret != sizeof(req_sn)-1) printf("bulk write error: %d\n", ret); ret=read_data((unsigned char*)ser, sizeof(ser)); if (ret < 0) printf("bulk read error: %d\n", ret); char s1[41],s3[31]=""; unsigned num=0; int n = sscanf(ser,"\x0d\x0a%40[^\n\r]%u\x0d\x0a%30[^\n\r]", s1, &num, s3); return strdup(s3); } TA* ftusbdevtx::GetFtTransferAreaAddress(int i) { if (i < N_EXT_DEV) if (ta[i]) return ta[i]; else printf("TX%d is not open\n", i); else printf("Index out of range (%d)\n", i); return 0; } unsigned ftusbdevtx::StartFtTransferArea(NOTIFICATION_EVENTS* ev) { int err = IsFtTransferActiv(); if (err == FTLIB_ERR_THREAD_IS_RUNNING) return err; if (active==0) return FTLIB_ERR_DEVICE_NOT_OPEN; if (ev) ne = *ev; //copy the entire struct else memset(&ne, 0, sizeof(NOTIFICATION_EVENTS)); FtThreadInit(); //sets busy to false transferAktiv = FTX1RUN;//indicate that thread is running return FTLIB_ERR_SUCCESS; } void ftusbdevtx::FtThreadBegin() { if (!test_and_set()) {//return when transferarea is in use busy = false; //release the mutex, otherwise the thread effectively stops printf("TA busy: skip begin slot\n"); return;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent } transferAktiv = FTX1SYNC;//indicate that TA is being updated (like busy) send_msg(2, active, false); increment(); } void ftusbdevtx::FtThreadEnd() { if (!test_and_set()) {//skip when busy busy = false; printf("TA busy: skip end slot\n"); return; } rec_msg(); //parse the message increment(); //release the TA mutex if (ne.NotificationCallback) { ne.NotificationCallback(ne.Context); } if (tid%100 == 0) { //about every 1 seconds //getSlaveInfo(); //synchronous! TODO: change to non-blocking } transferAktiv = FTX1RUN;//TA update complete busy = false; //ready for the next tick // printf("Busy released\n"); } UINT16 ftusbdevtx::checksum(unsigned char *p, unsigned n) { UINT16 sum = 0; do { sum -= *p++; } while (--n); return (sum<<8)|(sum>>8); } void ftusbdevtx::dump_buffer(int size) { if (buffer==0) { printf("No buffer\n"); return; } for (int i = 0; i < size; i++) { printf("%02X ", buffer[i]); if (i%16 == 15) printf("\n"); } printf("----------------------\n"); } unsigned ftusbdevtx::send_msg(unsigned cmd, unsigned set, bool sync) { const unsigned sizes[] = {0, 0, //cmd 1 sizeof(TA_OUTPUT)+sizeof(UINT32), //cmd 2 0, //unknown 0, //unknown sizeof(TA_CONFIG)+sizeof(UINT32), //cmd 5 sizeof(UINT32), //cmd 6 sizeof(UINT32), //cmd 7 sizeof(DISPLAY_MSG)+sizeof(UINT32), //cmd 8 DEV_NAME_LEN + 1+3 + sizeof(UINT32) //cmd 9 }; int ret = 0; int n = 0; for (int i = TA_LOCAL; i < TA_N_PARTS; i++) { if (set & (1<<i)) { n++; } } unsigned size = 0; if (cmd < sizeof(sizes)/sizeof(unsigned)) size = sizes[cmd]; unsigned payload_size = n*size; num_read = sizeof(header)+sizeof(trailer); unsigned total_size = sizeof(header)+payload_size+sizeof(trailer); buffer = new unsigned char[total_size]; //size must be known in advance unsigned net_size = total_size-sizeof(UINT32)-sizeof(trailer);//exclude start,len,crc,etx header *hdr = (header*)buffer; hdr->start = 0x5502; hdr->bytesH = net_size>>8; hdr->bytesL = net_size&0xff; hdr->body.snd = 2; hdr->body.rec = 1; hdr->body.trans = ++tid; hdr->body.session = sid; hdr->body.cmd = cmd; hdr->body.structs = n; unsigned char* payload = buffer+sizeof(header); for (int i = TA_LOCAL; i < TA_N_PARTS; i++) { if (ta[i]==0 || !(set & (1<<i))) { if (set & (1<<i)) printf("TX %d is not open yet!\n", i); continue; } unsigned *id = (unsigned*)payload; *id = i; payload = (unsigned char*)(id+1); num_read += sizeof(UINT32); switch (cmd) { case 1: break; case 2: memcpy(payload, &ta[i]->output, sizeof(TA_OUTPUT)); payload += sizeof(TA_OUTPUT); num_read += sizeof(TA_INPUT); break; case 5: memcpy(payload, &ta[i]->config, sizeof(TA_CONFIG)); payload += sizeof(TA_OUTPUT); break; case 6: num_read += sizeof(TA_INFO); break; case 7: num_read += sizeof(TA_STATE); break; case 8: memcpy(payload, &ta[i]->display.display_msg, sizeof(DISPLAY_MSG)); payload += sizeof(DISPLAY_MSG); break; case 9: memcpy(payload, ta[i]->info.device_name, DEV_NAME_LEN + 1+3); payload += sizeof(DEV_NAME_LEN + 1+3); break; default: printf("Unknown message type %d\n", cmd); break; } } trailer *trl = (trailer*)payload; trl->chksum = checksum(buffer+2, net_size+2); trl->etx = '\x03'; num_read--; //dump_buffer(total_size); //printf("Expecting %d bytes for transaction %d\n", num_read, tid); if (sync) { ret = write_data(buffer, total_size-1);//send 1 less because trailer is 1 too long due to alignment delete[] buffer; if (ret < 0) printf("synchronous send_message failed (%d)\n", ret); else { buffer = new unsigned char[num_read]; ret = read_data(buffer, num_read); if (ret < 0) { printf("synchronous read failed (%d)\n", ret); delete[] buffer; } else { //dump_buffer(num_read); rec_msg(); } } } else write_data(buffer, total_size-1, &ftusbdevtx::write_finished_cb, this); return ret; } #if 0 unsigned ftusbdevtx::rec_msg() { header *hdr = (header*)buffer; //dump_buffer(num_read); if (hdr->start != 0x5502) printf("Invalid packet\n"); unsigned net_size = (hdr->bytesH<<8) + hdr->bytesL; if (net_size+7 != num_read) printf("message has %d bytes, was expecting %d bytes\n", net_size+7, num_read); //printf("message %d from %d\n", hdr->cmd, hdr->snd); if (hdr->rec != 2) printf("Wrong destination (%d)\n", hdr->rec); if (hdr->trans != tid) printf("Response to request %d, expected %d\n", hdr->trans, tid); if (hdr->session != sid) { printf("Session number has changed from %d to %d\n", sid, hdr->session); sid = hdr->session; tid = 1; //restart transaction sequence } unsigned cmd = hdr->cmd - 100; unsigned n = hdr->structs; unsigned char* payload = buffer+sizeof(header); trailer *trl = (trailer*)(buffer+net_size+4); for (int i = 0; i < n && payload < (unsigned char*)trl; i++) { unsigned *id = (unsigned*)payload; if (*id >= TA_N_PARTS) { printf("Illegal extension nr %d\n", *id); continue; } if (ta[*id]==0) { printf("Message for new device %d\n", *id); continue;//skip the copy to avoid assignment to null ta but the payload pointer is not advanced! stopping further copying } payload = (unsigned char*)(id+1); switch (cmd) { case 1: break; case 2: memcpy(&ta[*id]->input, payload, sizeof(TA_INPUT)); payload += sizeof(TA_INPUT); break; case 5: break; case 6: memcpy(&ta[*id]->info, payload, sizeof(TA_INFO)); payload += sizeof(TA_INFO); break; case 7: memcpy(&ta[*id]->state, payload, sizeof(TA_STATE)); payload += sizeof(TA_STATE); break; case 8: break; case 9: break; default: printf("Unknown message type %d\n", cmd); break; } } if (payload != (unsigned char*)trl) printf("expected %d sections with in total %d bytes; got %d bytes\n", n, payload-buffer-sizeof(header), net_size-sizeof(header)); if (trl->chksum != checksum(buffer+2, net_size+2)) printf("Checksum error\n"); if (trl->etx != '\x03') printf("Expected ETX(03), got %02X\n", trl->etx); delete[] buffer; return 0; } #else unsigned ftusbdevtx::rec_msg() { header *hdr = (header*)buffer; //dump_buffer(num_read); if (hdr->start != 0x5502) printf("Invalid packet\n"); unsigned net_size = (hdr->bytesH<<8) + hdr->bytesL; if (net_size+7 != num_read) printf("message has %d bytes, was expecting %d bytes\n", net_size+7, num_read); rec_msg2(&hdr->body, net_size); trailer *trl = (trailer*)(buffer+net_size+4); if (trl->chksum != checksum(buffer+2, net_size+2)) printf("Checksum error\n"); if (trl->etx != '\x03') printf("Expected ETX(03), got %02X\n", trl->etx); delete[] buffer; return 0; } unsigned ftusbdevtx::rec_msg2(headerbody *hdr, unsigned net_size) { //printf("message %d from %d\n", hdr->cmd, hdr->snd); if (hdr->rec != 2) printf("Wrong destination (%d)\n", hdr->rec); if (hdr->trans != tid) printf("Response to request %d, expected %d\n", hdr->trans, tid); if (hdr->session != sid) { printf("Session number has changed from %d to %d\n", sid, hdr->session); sid = hdr->session; tid = 1; //restart transaction sequence } unsigned cmd = hdr->cmd - 100; unsigned n = hdr->structs; if (n==0) printf("Got reply to cmd %d\n", cmd); unsigned char* payload = (unsigned char *)(hdr+1); unsigned char* trl = (unsigned char*)hdr+net_size; for (int i = 0; i < n && payload < trl; i++) { unsigned *id = (unsigned*)payload; if (*id >= TA_N_PARTS) { printf("Illegal extension nr %d\n", *id); continue; } if (ta[*id]==0) { printf("Message for new device %d\n", *id); continue;//skip the copy to avoid assignment to null ta but the payload pointer is not advanced! stopping further copying } payload = (unsigned char*)(id+1); switch (cmd) { case 1: break; case 2: memcpy(&ta[*id]->input, payload, sizeof(TA_INPUT)); payload += sizeof(TA_INPUT); break; case 5: break; case 6: memcpy(&ta[*id]->info, payload, sizeof(TA_INFO)); payload += sizeof(TA_INFO); break; case 7: memcpy(&ta[*id]->state, payload, sizeof(TA_STATE)); payload += sizeof(TA_STATE); if (*id == 0) for (int i = 1; i <= N_EXT_DEV; i++) if (ta[0]->state.ext_dev_connect_state[i-1]) { if (!(active & (1<<i))) { //new slave active |= 1<<i; if (ta[i] == 0) { //new slave ta[i] = new TA; memset(ta[i], 0, sizeof(TA)); } send_msg(6, 1<<i, false); //get info for slave; printf("New Extension %d = %s\n", i, ta[i]->info.device_name); if (cbRoboExtState) cbRoboExtState(i, 1); } } else { if (active & (1<<i)) { active &= ~(1<<i); printf("Extension %d went offline\n", i); if (cbRoboExtState) cbRoboExtState(i, 0); } } break; case 8: break; case 9: break; default: printf("Unknown message type %d\n", cmd); break; } } if (payload != trl) printf("expected %d sections with in total %d bytes; got %d bytes\n", n, payload-(unsigned char*)(hdr+1), net_size-sizeof(headerbody)); return cmd; } #endif void ftusbdevtx::read_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) { //end of reply transfer //printf("read_finished_cb: %d bytes\n", len); ftusbdevtx *fth = (ftusbdevtx*)userData; if (fth->transferAktiv == FTX1SYNC) fth->FtThreadEnd(); else fth->rec_msg(); } void ftusbdevtx::write_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) { //end of request transfer, issue, reply transfer ftusbdevtx *fth = (ftusbdevtx*)userData; //printf("write_finished_cb: wrote %d bytes, reading %d bytes\n", len, fth->num_read); delete[] fth->buffer; fth->buffer = new unsigned char[fth->num_read]; USBInterruptTransfer(fth->device, 0x82, fth->buffer, fth->num_read, read_finished_cb, fth); }