class library to access fischertechnik interfaces via USB
Dependencies: FatFileSystem mbed myBlueUSB neigbourhood rfcomm sdp
ftlib/ftlibclasscom.cpp
- Committer:
- networker
- Date:
- 2013-03-11
- Revision:
- 1:4676e8b9b357
- Parent:
- 0:7da612835693
File content as of revision 1:4676e8b9b357:
#include "mbed.h" #include "ftlibclasscom.h" vector<ftcommdev*> ftcommdev::devs; ftcommdev::ftcommdev(Serial *s, unsigned t, unsigned c): ftdev(t, 0) { device = s; port = 0; FT_TRANSFER_AREA *area = new FT_TRANSFER_AREA; memset(area, 0, sizeof(struct _FT_TRANSFER_AREA)); area->TransferAktiv = 0; //query_time = INTERFACE_QUERY_TIME_SERIAL; area->RfModulNr = -1; if (t == FT_INTELLIGENT_IF) area->BusModules = 1; else if (t == FT_INTELLIGENT_IF_SLAVE) area->BusModules = 2; ta = area; } //blocking int ftcommdev::read(Serial *stream, unsigned char *buf, int n, int timeout_ms) { Timer t; t.start(); int i = 0; while (t.read_ms() < timeout_ms && i < n) { if (stream->readable()) buf[i++] = stream->getc(); } return i; } int ftcommdev::write(Serial *d, unsigned char *ptr, int n, int timeout_ms) { Timer t; t.start(); int i = 0; while (t.read_ms() < timeout_ms && i < n) { if (d->writeable()) d->putc(ptr[i++]); } return i; } //non-blocking int ftcommdev::write() { windex = 0; writeByte(); //write the first byte, callback will take care of the rest return num_write; } void ftcommdev::writeByte() { if (windex < num_write) { device->putc(out[windex++]); if (windex == num_write) rindex = 0; } } void ftcommdev::readByte() { if (rindex < num_read) { in[rindex++] = device->getc(); if (rindex == num_read) { FtThreadEnd(); } } } ftcommdev* ftcommdev::OpenFtCommDevice(unsigned sDevice, unsigned dwTyp, unsigned dwZyklus, unsigned *pdwError) {//makes a (blocking) comm request to the interface Serial *dev = 0; switch (sDevice) { case 1: dev = new Serial(p9, p10); break; case 2: dev = new Serial(p13, p14); break; case 3: dev = new Serial(p28, p27); break; // default: dev = new Serial(p9, p10); break; default: // dev = &viaUsb; break; } ftcommdev* com = OpenFtCommDevice(dev, dwTyp, dwZyklus, pdwError); if (com) { com->port = sDevice; printf("opening of COM%d OK\n", sDevice); } return com; } ftcommdev* ftcommdev::OpenFtCommDevice(Serial *dev, unsigned dwTyp, unsigned dwZyklus, unsigned *pdwError) {//makes a (blocking) comm request to the interface unsigned char in[5]; unsigned char on[] = " ft-Robo-ON-V1"; on[0] = 0xA1; ftcommdev* ret = 0; if (dwTyp != FT_ROBO_IF_COM) { ret = new ftcommdevii(dev, dwTyp, dwZyklus); dev->baud(BAUDRATE_II); } else {// dwTyp == FT_ROBO_IF_COM ret = new ftcommdev(dev, dwTyp, dwZyklus); dev->baud(BAUDRATE_RI); } printf("about to send '%s'\n", on); if (dwTyp == FT_ROBO_IF_COM) { int sent = write(dev, on, strlen((const char*)on), 100/*ms*/); // int sent = dev->printf("%s", on); printf("sent %d bytes to COM\n", sent); if (sent == strlen((const char*)on)) { if (read(dev, in, 5, 1000/*ms*/) == 5) { // if (dev->scanf("%5c", in) == 1) { does not work, could have to do with NUL chars or needs a lookahead char printf("%02X: interface version: %d.%d.%d.%d\n", in[0], in[4], in[3], in[2], in[1]); ret->fw = *(unsigned*)(in+1); if ((in[0] ^ on[0]) == 0x0FFU) { printf("opening of %s OK\n", "UNKNOWN"); } else { printf("return code is %02X but should be %02X\n", in[0], ~on[0]&0xFF); delete ret; return NULL; } } else { printf("read did not return 5\n"); delete ret; return NULL; } } else { printf("only %d chars were sent i.o %d\n", sent, strlen((const char*)on)); delete ret; return NULL; } } devs.push_back(ret); return ret; } unsigned ftcommdev::CloseFtDevice() {//sends a comm request unsigned char off = 0xA2; unsigned char in[1]; while (ta->TransferAktiv != 0) { fprintf(stderr, "Transfer ta still active\n"); sleep(1); } if (type == FT_ROBO_IF_COM) { if (write(device, &off, 1, 500) != 1 || read(device, in, 1, 1000) != 1 || (in[0]^off != 0xFF)) { fprintf(stderr, "CloseFtDevice: Error communicating with serial\n"); } } for (vector<ftcommdev*>::iterator it = devs.begin(); it < devs.end(); it++) if (*it == this) { devs.erase(it); delete this; return 0; } return 0; } unsigned ftcommdev::GetFtSerialNr() { int ret; unsigned char buffer[35] = { 0 }; if (sn > 0) return sn; switch (type) { case FT_INTELLIGENT_IF: case FT_INTELLIGENT_IF_SLAVE: return 0; case FT_ROBO_IF_COM: buffer[0] = 0xf0; buffer[1] = 0x02; ret = write(device, buffer, 2, 500); if (ret != 2) { fprintf(stderr, "Error writing msg 0xF0 0x02\n"); return 0; } ret = read(device, buffer, 5, 1000); if (ret != 5) { fprintf(stderr, "Error reading msg 0xF0 0x02\n"); return 0; } //sn = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000; sn = *(unsigned*)(buffer+1); break; default: return FTLIB_ERR_NOT_SUPPORTED; } return sn; } char * ftcommdev::GetFtLongNameStrg() { switch (type) { case FT_INTELLIGENT_IF: return strdup("Intelligent Interface"); case FT_INTELLIGENT_IF_SLAVE: return strdup("Intelligent Interface with Slave"); case FT_ROBO_IF_IIM: return strdup("Robo Interface in Intelligent Interface mode"); case FT_ROBO_IF_COM: return strdup("Robo Interface on Com"); default: return strdup("Unknown interface type"); } } char * ftcommdev::GetFtShortNameStrg() { switch (type) { case FT_INTELLIGENT_IF: return strdup("IIF"); case FT_INTELLIGENT_IF_SLAVE: return strdup("IIF w/Slave"); case FT_ROBO_IF_IIM: return strdup("RI_IIM"); case FT_ROBO_IF_COM: return strdup("RICom"); default: return strdup("Unknown"); } } void ftcommdev::poll() { for (int i = 0; i < devs.size(); i++) { if (devs[i]->triggered) { if (devs[i]->guardedFtThreadBegin()) devs[i]->triggered = 0; } } } void ftcommdev::FtThreadInit() {//setup buffers for this type of interface device->attach(this, &ftcommdev::writeByte, Serial::TxIrq); device->attach(this, &ftcommdev::readByte, Serial::RxIrq); ftdev::FtThreadInit(); out[0] = 0xf2; num_write = 17; num_read = 21; } //here the real data exchange starts void ftcommdev::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking if (!test_and_set()) {//return when transferarea is in use busy = false; //release the mutex, otherwise the thread effectively stops 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 } out[1] = ta->M_Main; out[2] = (ta->MPWM_Main[0] & 0x7) | (ta->MPWM_Main[1]<<3 & 0x38) | (ta->MPWM_Main[2]<<6 & 0xC0); out[3] = (ta->MPWM_Main[2] & 0x1) | (ta->MPWM_Main[3]<<1 & 0xE) | (ta->MPWM_Main[4]<<4 & 0x70) | (ta->MPWM_Main[5]<<7 & 0x80); out[4] = (ta->MPWM_Main[5] & 0x3) | (ta->MPWM_Main[6]<<2 & 0x1C) | (ta->MPWM_Main[7]<<5 & 0xE0); out[5] = ta->M_Sub1; out[6] = (ta->MPWM_Sub1[0] & 0x7) | (ta->MPWM_Sub1[1]<<3 & 0x38) | (ta->MPWM_Sub1[2]<<6 & 0xC0); out[7] = (ta->MPWM_Sub1[2] & 0x1) | (ta->MPWM_Sub1[3]<<1 & 0xE) | (ta->MPWM_Sub1[4]<<4 & 0x70) | (ta->MPWM_Sub1[5]<<7 & 0x80); out[8] = (ta->MPWM_Sub1[5] & 0x3) | (ta->MPWM_Sub1[6]<<2 & 0x1C) | (ta->MPWM_Sub1[7]<<5 & 0xE0); out[9] = ta->M_Sub2; out[10] = (ta->MPWM_Sub2[0] & 0x7) | (ta->MPWM_Sub2[1]<<3 & 0x38) | (ta->MPWM_Sub2[2]<<6 & 0xC0); out[11] = (ta->MPWM_Sub2[2] & 0x1) | (ta->MPWM_Sub2[3]<<1 & 0xE) | (ta->MPWM_Sub2[4]<<4 & 0x70) | (ta->MPWM_Sub2[5]<<7 & 0x80); out[12] = (ta->MPWM_Sub2[5] & 0x3) | (ta->MPWM_Sub2[6]<<2 & 0x1C) | (ta->MPWM_Sub2[7]<<5 & 0xE0); out[13] = ta->M_Sub3; out[14] = (ta->MPWM_Sub3[0] & 0x7) | (ta->MPWM_Sub3[1]<<3 & 0x38) | (ta->MPWM_Sub3[2]<<6 & 0xC0); out[15] = (ta->MPWM_Sub3[2] & 0x1) | (ta->MPWM_Sub3[3]<<1 & 0xE) | (ta->MPWM_Sub3[4]<<4 & 0x70) | (ta->MPWM_Sub3[5]<<7 & 0x80); out[16] = (ta->MPWM_Sub3[5] & 0x3) | (ta->MPWM_Sub3[6]<<2 & 0x1C) | (ta->MPWM_Sub3[7]<<5 & 0xE0); out[17] = 0; out[18] = 0; out[19] = 0; out[20] = 0; out[21] = 0; out[22] = 0; out[23] = 0; out[24] = 0; out[25] = 0; out[26] = 0; out[27] = 0; out[28] = 0; out[29] = 0; out[30] = 0; out[31] = 0; increment();//release the lock on shared memeory write(); } #if 0 void ftcommdev::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete if (!test_and_set()) {//skip when busy busy = false; return; } ta->ChangeEg = ta->E_Main != in[0] || ta->E_Sub1 != in[1] || ta->E_Sub2 != in[2] || ta->E_Sub3 != in[3]; ta->E_Main = in[0]; ta->E_Sub1 = in[1]; ta->E_Sub2 = in[2]; ta->E_Sub3 = in[3]; ta->ChangeAn = 1; //assume that analog always changes (noise) ta->AX = in[4]; ta->AY = in[5]; ta->A1 = in[6]; ta->A2 = in[7]; ta->AX |= (in[8] & 0x3) << 8; ta->AY |= (in[8] & 0xC) << 6; ta->A1 |= (in[8] & 0x30) << 4; ta->A2 |= (in[8] & 0xC0) << 2; ta->AZ = in[9]; ta->D1 = in[10]; ta->D2 = in[11]; ta->AV = in[12]; ta->AZ |= (in[13] & 0x3) << 8; ta->D1 |= (in[13] & 0xC) << 6; ta->D2 |= (in[13] & 0x30) << 4; ta->AV |= (in[13] & 0xC0) << 2; if (ta->IRKeys != in[14]) ta->ChangeIr = 1; ta->IRKeys = in[14]; ta->BusModules = in[15]; // 16 ta->AXS1 = in[17]; ta->AXS2 = in[18]; ta->AXS3 = in[19]; ta->AXS1 |= (in[20] & 0x3) << 8; ta->AXS2 |= (in[20] & 0xC) << 6; ta->AXS3 |= (in[20] & 0x30) << 4; // 21 ta->AVS1 = in[22]; ta->AVS2 = in[23]; ta->AVS3 = in[24]; ta->AVS1 |= (in[25] & 0x3) << 8; ta->AVS2 |= (in[25] & 0xC) << 6; ta->AVS3 |= (in[25] & 0x30) << 4; // 26...42 increment(); interface_connected = 1; if (ne.NotificationCallback) { (*ne.NotificationCallback)(ne.Context); } busy = false; } #endif void ftcommdev::FtThreadFinish() {//called by StopFtTransferArea device->attach(0,Serial::RxIrq); device->attach(0,Serial::TxIrq); ftdev::FtThreadFinish(); } void ftcommdevii::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking if (!test_and_set()) {//return when transferarea is in use busy = false; //release the mutex, otherwise the thread effectively stops 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 } out[1] = ta->M_Main; out[2] = ta->M_Sub1; // For the II we need to simulate different speeds here for (int iCurMotor = 0; iCurMotor < 7; iCurMotor++) { if (ta->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor); if (ta->MPWM_Sub1[iCurMotor] < ii_speed) out[2] &= ~(1 << iCurMotor); } ii_speed++; if (ii_speed > 7) ii_speed = 0; num_write=2; switch (cycle) { case 0: num_read=3; out[0] = 0xc5; break; case 1: num_read=3; out[0] = 0xc9; break; default: num_read=1; out[0] = 0xc1; break; } if (type == FT_INTELLIGENT_IF_SLAVE) { num_write++; num_read++; out[0]++; } if (cycle++ > analogcycle) cycle=0; increment();//release the lock on shared memeory write(); } void ftcommdevii::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete if (!test_and_set()) {//skip when busy busy = false; return; } ta->ChangeEg = ta->E_Main != in[0]; ta->E_Main = in[0]; ta->BusModules = type==FT_INTELLIGENT_IF_SLAVE; switch (out[0]) { case 0xc1: break; case 0xc5: ta->AX = in[1] | (8<<in[2]); break; case 0xc9: ta->AY = in[1] | (8<<in[2]); break; case 0xc2: ta->ChangeEg = ta->ChangeEg || ta->E_Sub1 != in[1]; ta->E_Sub1 = in[1]; break; case 0xc6: ta->ChangeEg = ta->ChangeEg || ta->E_Sub1 != in[1]; ta->E_Sub1 = in[1]; ta->AX = in[2] | (8<<in[3]); break; case 0xca: ta->ChangeEg = ta->ChangeEg || ta->E_Sub1 != in[1]; ta->E_Sub1 = in[1]; ta->AY = in[2] | (8<<in[3]); break; } increment(); interface_connected = 1; if (ne.NotificationCallback) { (*ne.NotificationCallback)(ne.Context); } busy = false; } unsigned ftcommdev::SetFtDistanceSensorMode(unsigned dwMode, unsigned dwTol1, unsigned dwTol2, unsigned dwLevel1, unsigned dwLevel2, unsigned dwRepeat1, unsigned dwRepeat2) { unsigned char buffer[11]; if (type != FT_ROBO_IF_COM) return FTLIB_ERR_NOT_SUPPORTED; buffer[0] = 0xf1; buffer[1] = 0x01; buffer[2] = dwMode; buffer[3] = dwTol1; buffer[4] = dwTol2; buffer[5] = dwLevel1; buffer[6] = dwLevel1>>8; buffer[7] = dwLevel2; buffer[8] = dwLevel2>>8; buffer[9] = dwRepeat1; buffer[10] = dwRepeat2; if ((write(device, buffer, 11, 500)) != 11 || (read(device, buffer, 1, 500)) != 1 || buffer[0] != 0x01) { fprintf(stderr, "SetFtDistanceSensorMode: Error communicating with serial\n"); return buffer[0]; } usleep(100000); // wait before continue, else it doesn't always work return FTLIB_ERR_SUCCESS; } unsigned ftcommdev::pgm_message(unsigned code, unsigned dwMemBlock) { unsigned char buffer[2]; if (type != FT_ROBO_IF_COM) return FTLIB_ERR_NOT_SUPPORTED; buffer[0] = code; buffer[1] = dwMemBlock; if ((write(device, buffer, 2, 500)) != 2 || (read(device, buffer, 1, 500)) != 1) { return FTLIB_ERR_IF_NO_PROGRAM; } if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; else return FTLIB_ERR_IF_NO_PROGRAM; }