diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md new file mode 100644 index 0000000..e08b564 --- /dev/null +++ b/CONTRIBUTE.md @@ -0,0 +1,66 @@ +# How to publish your work in an ABS repository +Despite the ABS GitHub repositories being open to the community, they are internally managed and are subject to reviews. The review process prevents the master repo from containing wrong, incomplete or inconsistent code (or designs), and is oriented to provide detailed feedback on your proposed implementations. The ABS repositories are peer-reviewed by [M. MarĂ­](mailto:marc.mari.barcelo@est.fib.upc.edu) (*mark-mb*) and [C. Araguz](mailto:carles.araguz@upc.edu) (*carlesaraguz*), who will post their comments to you implementations through this GitHub web platform. The review process is decomposed into the following steps: + + 1. You fork the ABS repo in which you will be working (Software, Hardware or ARTOS). + 2. Push your local commits to your forked repo. + 3. Include a **detailed** `README.md` file explaining how to open/compile/test your files. Remember to include references to other communities (e.g. other repo's) if you have used libraries or special assets. External assets such as libraries, should not be included in ABS repo's unless it is strictly necessary (see note below). + 3. Issue a [*pull-request*](https://help.github.com/articles/using-pull-requests/). + 4. In your pull-request form, provide thorough details of your changes, design, important sections or aspects that you consider important during the review process (e.g. unimplemented sections, purposefully ignored warnings and their justification, hard-coded parts that you expect to modify later, etc.) + 5. The reviewers will read, compile and execute your code and provide feedback. + 6. Then: + * If your pull-request is **accepted** but requires some changes, you should provide them in the form of a new pull-request (step 4). The master repository will include your previous commits. + * If your pull-request is **rejected**, you need to fix your issues as soon as possible and generate a new pull-request (step 4). Remember that if this happened after the FDR, your course mark may rely on this second/fixed pull-request. + +#### General recommendations +* Start working on your local repository from the beginning. Using a GIT repository not only will allow you to recover previous versions or keep your developments well organised but will also allow you to issue several pull-requests during the course (and have them reviewed before the FDR). +* Coordinate your efforts with the rest of collaborators so that you work in the appropriate folder from the beginning. Remember that the repository structure and file naming is also managed and has to be agreed with the rest of team members. +* Read the repository's rules ***carefully*** (e.g. *CODING_STYLES.md*) before issuing your pull-requests. + +#### A note about external libraries or assets +You may include external code or designs (e.g. libraries) if: + +* The external assets comply to the repository rules (i.e. no binaries, well documented, open-source, etc.) +* You have performed some modifications to those assets or you are using modified versions that can't be get from official sources. +* You always give credit to the original author(s) / source(s). +* You justify your decision. + +#### General rules for the ABS software repository (*abs-software*) +These repositories shall only include software-related development such as: software architecture modules, Arduino firmware, microcontroller's firmware. The repo **must never include**: + +* Project files (i.e. the kind of garbage left by programming IDE's such as NetBeans, Eclipse or MPLAB) +* Autogenerated Makefiles that can only be executed by the programming IDE. +* Binaries or built sources. +* Programs that are not compliant with the coding styles (exception: code that you have not written, such as external libraries or headers). + +#### General rules for the ABS hardware repository (*abs-hardware*) +Given that most PCB design frameworks don't usually generate text files, hardware designs must be kept in different folders according to their version. For PCB designs, the following (minimum) files have to be included: + +* The schematic (e.g. *".SchDoc"*) +* The PCB layout (e.g. *".PcbDoc"*) +* A PDF file with the schematic (organised in several pages, if needed) and layout (in a way that all layers can be seen, e.g. each layer in a different page). +* The fabrication files (layers in Gerber format), as they would be sent to the manufacturer company. +* A bill-of-materials Excel (or LibreOffice / Google Docs spreadsheet) with, at least, the following columns: + * The component description and *value* (e.g. "Resistor 1k2", "RF transmitter", "Inductor 23 mH"); + * the component name(s) as shown in schematics and silk-screen layer (e.g. IC23, C34, R2, L1); + * the manufacturer's reference (e.g. LT3129); + * the footprint/case reference; + * the purchasing reference (e.g. Farnell product ID) and a descriptive comment; + * and the quantity. +* A `README.md` file with stating: + * The **version number** and name of the software that has been used to generate the files (e.g. "Altium Designer v15.43.2") + * Special fabrication requirements, if any (e.g. FR4 substrate). + +May be included in the repository: footprint libraries for non-standard components, a `Datasheets` folder containing PDF component datasheets. + +##### Folder naming +All PCB designs must be placed in folders applying the following naming rules: + + UPCNSL-ABS-XXX-YYY-vN.NN + +Where: + +* `UPC-NSL-ABS` is the generic codename for ABS boards from the NanoSat Lab / UPC. +* `XXX` is the subsystem: `ARDS` (for Arduino Space board), `EPS` (Electrical Power Subsystem boards, such as the PV panels), `POL` (for Point-of-Load boards), `COMMS` (for RF boards of the comms. subsystem). +* `YYY` is a secondary nomenclature indicating the type of board (e.g. `TEST`, `PLATFORM`, `FLATSAT`...) +* `vN.NN` is the version number (e.g. `v1.2`) +* All files inside a PCB folder **must** be prefixed with the folder name. \ No newline at end of file diff --git a/src/Arduino/abs/IntegrationFirmwareDocumentation.docx b/src/Arduino/abs/IntegrationFirmwareDocumentation.docx new file mode 100644 index 0000000..b8c95e6 Binary files /dev/null and b/src/Arduino/abs/IntegrationFirmwareDocumentation.docx differ diff --git a/src/Arduino/abs/IntegrationFirmwareDocumentation.pdf b/src/Arduino/abs/IntegrationFirmwareDocumentation.pdf new file mode 100644 index 0000000..e2efcdc Binary files /dev/null and b/src/Arduino/abs/IntegrationFirmwareDocumentation.pdf differ diff --git a/src/Arduino/abs/README_comms.md b/src/Arduino/abs/README_comms.md new file mode 100644 index 0000000..9e805b7 --- /dev/null +++ b/src/Arduino/abs/README_comms.md @@ -0,0 +1,24 @@ +# COMMS DRIVER + +## Definition + +In the comms driver it has been implemented all the functionalities for the AX5042 transceiver. The required algorithms for the transmission and reception routines are implemented in files hdlc.c and comms.cpp. These contain Main functions (configure, change_x, transmit and receive) . The final SPI connection between the arduino board and the +transceiver is also defined here through the functions write_register and read_register. + +The main code in the comms driver is structured as a class using c++. If using the Arduino IDE, the driver must be imported following the procedure for its IDE. + +## Modifications from the previous version +1. Fix errors from the previous version. +2. Addition of one configuration function for each register. +3. Restructuring of the configuration code using functions mentioned in the previous statement. +4. Analysis of the dependencies between registers in order to implement change_x function. Implementation of change_x function. +5. Change the reception algorithm to make an error control and send back to the HWmod all the packet. +6. Integration of the new comms driver version in the Arduino firmware. +7. Creation of new _structs_ and _enums_ in the Arduino firmware. +8. Develop comms_test to test the execution time of configuration and change_x routines. + + +## Future modifications (expected in a few weeks) +1. Implementation of a reception event in order to update the reception info every some time and avoid stopping Arduino from its main routine. + - Option B. Using interruptions from the transceiver (FIFO full, FIFO empty...). +2. Adaptation of communication protocol with HWmod. \ No newline at end of file diff --git a/src/Arduino/abs/abs.ino b/src/Arduino/abs/abs.ino index 4ec0c04..d8829a2 100644 --- a/src/Arduino/abs/abs.ino +++ b/src/Arduino/abs/abs.ino @@ -1,3 +1,5 @@ +#include "abs_comms.h" +#include "abs_hdlc.h" #include #include #include @@ -7,116 +9,238 @@ #include #include #include "abs.h" -#include -#include Comms comms; +/*Define pre-complier variables*/ +#define FINAL 0 +#define COMMS_TEST 1 +#define ABS_TEST 2 +#ifndef test_version +#define test_version COMMS_TEST +#endif + +/* initializations */ Servo myServo[MAX_SERVO]; -SoftwareSerial mySerial[MAX_SERIAL] = {SoftwareSerial(10,11), SoftwareSerial(7,8)}; +SoftwareSerial mySerial[MAX_SERIAL] = {SoftwareSerial(10, 11), SoftwareSerial(7, 8)}; File buffer; USB Usb; Event event_list[MAX_EVENTS]; + +/*initialize Variables*/ +#if test_version == COMMS_TEST +int timer = 0, eventCount = 0, packetCount = 0; +char str[80]; +int config_done, config_time; +int changex_done, changex_time; +int transmit_done, transmit_time; +#else int time = 0, eventCount = 0, packetCount = 0; +#endif ADK adk(&Usb, "UPC, BarcelonaTech", - "Android Beyond the Stratoshpere", - "Android Beyond the Stratoshpere", - "1.0", - "http://www.upc.edu", - "000000000000000001"); + "Android Beyond the Stratoshpere", + "Android Beyond the Stratoshpere", + "1.0", + "http://www.upc.edu", + "000000000000000001"); void reboot(void) { - wdt_enable(WDTO_15MS); - while(1); + wdt_enable(WDTO_15MS); + while (1); } void setup(void) { - Serial.begin(SERIAL_BITRATE); - Serial.println("\r\nArduino firmware start"); +#if test_version == COMMS_TEST + Serial.begin(SERIAL_BITRATE); + Serial.println("\r\nArduino firmware start"); - if(Usb.Init() == -1) { - Serial.println("OSCOKIRQ failed to assert"); - while(Usb.Init() == -1); /* retry */ - } + Timer1.initialize(TIMER_INTERVAL); + Timer1.pwm(9, 512); + Timer1.attachInterrupt(events_routine); - Timer1.initialize(TIMER_INTERVAL); - Timer1.pwm(9, 512); - Timer1.attachInterrupt(events_routine); + pinMode(SD_CS, OUTPUT); - pinMode(SD_CS, OUTPUT); - - if (!SD.begin(SD_CS)) { - Serial.println("Error initializing SDcard"); - } + Serial.println("Setup Ok\n"); - Serial.println("Setup Ok\n"); -} +#elif test_version == ABS_TEST + Serial.begin(SERIAL_BITRATE); + Serial.println("\r\nArduino firmware start"); -void loop(void) -{ - USBPacket *packet; - USBPacket *pkt_res; - uint8_t *response; - uint8_t msg[MAX_PACKET_SIZE]; - int i = 0; - char str[80]; - uint8_t ret; - uint16_t len; + if (Usb.Init() == -1) { + Serial.println("OSCOKIRQ failed to assert"); + while (Usb.Init() == -1); /* retry */ + } - Usb.Task(); + Timer1.initialize(TIMER_INTERVAL); + Timer1.pwm(9, 512); + Timer1.attachInterrupt(events_routine); - if(!adk.isReady()) { - Serial.println("ADK not ready\n"); - return; - } + pinMode(SD_CS, OUTPUT); - len = sizeof(msg); - adk.RcvData(&len, msg); - if(len > 0) { - packet = process_packet(msg); + if (!SD.begin(SD_CS)) { + Serial.println("Error initializing SDcard"); + } - sprintf(str, "Received %d %d:%d %d:%d:%d", packet->packet_id, - packet->command, packet->parameters, packet->cmd_arg1, - packet->cmd_arg2, packet->data_size); - Serial.println(str); + Serial.println("Setup Ok\n"); + #else + /*place final integrated code here*/ +#endif +} - pkt_res = execute_packet(packet); - free(packet); +void loop(void) { - sprintf(str, "Result %d %d:%d %d:%d:%d", pkt_res->packet_id, - pkt_res->command, pkt_res->parameters, pkt_res->cmd_arg1, - pkt_res->cmd_arg2, pkt_res->data_size); - Serial.println(str); +#if test_version == COMMS_TEST - response = to_raw(pkt_res, &len); - free(pkt_res); +USBPacket *packet; + USBPacket *pkt_res; + char str[80]; + uint8_t ret; + uint16_t len; - adk.SndData(len, response); - free(response); + packet = (USBPacket *)malloc(sizeof(*packet)); + + packet->packet_id = 1; + packet->command = COMMS; + packet->parameters = CONFIGURE; + + sprintf(str, "Received %d %d:%d %d:%d:%d", packet->packet_id, + packet->command, packet->parameters, packet->cmd_arg1, + packet->cmd_arg2, packet->data_size); + Serial.println(str); + + pkt_res = (USBPacket *)malloc(sizeof(*pkt_res)); + pkt_res = execute_packet(packet); + free(packet); + + sprintf(str, "Result %d %d:%d %d:%d:%d", pkt_res->packet_id, + pkt_res->command, pkt_res->parameters, pkt_res->cmd_arg1, + pkt_res->cmd_arg2, pkt_res->data_size); + Serial.println(str); + + free(pkt_res); + config_done = 1; + + packet->packet_id = 2; + packet->command = COMMS; + packet->parameters = CHANGE_X; + packet->cmd_arg1 = BITRATE; + packet->cmd_arg2 = 50000; + + + sprintf(str, "Received %d %d:%d %d:%d:%d", packet->packet_id, + packet->command, packet->parameters, packet->cmd_arg1, + packet->cmd_arg2, packet->data_size); + Serial.println(str); + + pkt_res = execute_packet(packet); + free(packet); + + sprintf(str, "Result %d %d:%d %d:%d:%d", pkt_res->packet_id, + pkt_res->command, pkt_res->parameters, pkt_res->cmd_arg1, + pkt_res->cmd_arg2, pkt_res->data_size); + Serial.println(str); + + free(pkt_res); + changex_done = 1; + +#elif test_version == ABS_TEST + USBPacket *packet; + USBPacket *pkt_res; + uint8_t *response; + uint8_t msg[MAX_PACKET_SIZE]; + int i = 0; + char str[80]; + uint8_t ret; + uint16_t len; + + Usb.Task(); + + if (!adk.isReady()) { + Serial.println("ADK not ready\n"); + return; + } + + len = sizeof(msg); + adk.RcvData(&len, msg); + if (len > 0) { + packet = process_packet(msg); + + sprintf(str, "Received %d %d:%d %d:%d:%d", packet->packet_id, + packet->command, packet->parameters, packet->cmd_arg1, + packet->cmd_arg2, packet->data_size); + Serial.println(str); + + pkt_res = execute_packet(packet); + free(packet); + + sprintf(str, "Result %d %d:%d %d:%d:%d", pkt_res->packet_id, + pkt_res->command, pkt_res->parameters, pkt_res->cmd_arg1, + pkt_res->cmd_arg2, pkt_res->data_size); + Serial.println(str); + + response = to_raw(pkt_res, &len); + free(pkt_res); + + adk.SndData(len, response); + free(response); + } + + for (i = 0; i < eventCount; i++) { + if (event_list[i].execute == 1) { + pkt_res = execute_packet(event_list[i].action); + save_event_data(i, pkt_res); + free(pkt_res); + event_list[i].execute = 0; } + } - for(i = 0; i < eventCount; i++) { - if(event_list[i].execute == 1) { - pkt_res = execute_packet(event_list[i].action); - save_event_data(i, pkt_res); - free(pkt_res); - event_list[i].execute = 0; - } - } + #else + /*place final integrated code here*/ +#endif } void events_routine(void) { - int i = 0; - for(i = 0; i < eventCount; i++) { - if(time % event_list[i].interval == 0) { - Serial.println("Event!!!"); - event_list[i].execute = 1; - } + #if test_version == COMMS_TEST + /*TIMER_INTERVAL has us units*/ + if(config_done) { + config_time = timer * TIMER_INTERVAL / 1000; + config_done = 0; + sprintf(str, "The execution time of configuration was %d ms", config_time); + Serial.println(str); + timer = 0; + + } else if(changex_done) { + changex_time = timer * TIMER_INTERVAL / 1000; + changex_done = 0; + sprintf(str, "The execution time of change_X was %d ms", changex_time); + Serial.println(str); + timer = 0; + + } else if(transmit_done) { + transmit_time = timer * TIMER_INTERVAL / 1000; + transmit_done = 0; + sprintf(str,"The execution time of transmit was %d ms", transmit_time); + Serial.println(str); + timer = 0; } - time++; + timer++; + + #elif test_version == ABS_TEST + int i = 0; + for (i = 0; i < eventCount; i++) { + if (time % event_list[i].interval == 0) { + Serial.println("Event!!!"); + event_list[i].execute = 1; + } + } + time++; + + #else + /*place final integrated code here*/ + #endif } diff --git a/src/Arduino/abs/abs_assets.ino b/src/Arduino/abs/abs_assets.ino new file mode 100644 index 0000000..4f7d356 --- /dev/null +++ b/src/Arduino/abs/abs_assets.ino @@ -0,0 +1,312 @@ +USBPacket *usb_ok_packet(int id) +{ + USBPacket *packet = (USBPacket *)malloc(sizeof(*packet)); + packet->command = CONTROL; + packet->parameters = OK; + packet->cmd_arg1 = 0; + packet->cmd_arg2 = 0; + packet->data_size = 0; + packet->packet_id = id; + return packet; +} + +USBPacket *usb_abort_packet(int id) +{ + USBPacket *packet = (USBPacket *)malloc(sizeof(*packet)); + packet->command = CONTROL; + packet->parameters = ABORT; + packet->cmd_arg1 = 0; + packet->cmd_arg2 = 0; + packet->data_size = 0; + packet->packet_id = id; + return packet; +} + +USBPacket *usb_ok_data_packet(int id, char *result, int dsize) +{ + USBPacket *packet = (USBPacket *)malloc(sizeof(*packet)); + packet->command = CONTROL; + packet->parameters = OK_DATA; + packet->data_size = dsize; + packet->data = (uint8_t *)result; + packet->packet_id = id; + return packet; +} + +USBPacket *usb_error_packet(int id, int error) +{ + USBPacket *packet = (USBPacket *)malloc(sizeof(*packet)); + packet->command = CONTROL; + packet->parameters = ERRORS; + packet->cmd_arg1 = error; + packet->data_size = 0; + packet->packet_id = id; + return packet; +} + +int save_event_data(int buffer_id, USBPacket *packet) +{ + Serial.println("Data saved"); + String temp = "buffer"; + temp.concat(buffer_id); + temp.concat(".txt"); + char filename[temp.length() + 1]; + temp.toCharArray(filename, sizeof(filename)); + + buffer = SD.open(filename, FILE_WRITE); + if(buffer) { + buffer.write(packet->data, packet->data_size); + buffer.close(); + return 1; + } else { + return 0; + } +} + +char dumpData(int buffer_id) +{ + String temp = "buffer"; + temp.concat(buffer_id); + temp.concat(".txt"); + char filename[temp.length() + 1]; + temp.toCharArray(filename, sizeof(filename)); + File dataFile = SD.open(filename); + char data; + if (dataFile) { + noInterrupts(); + if(dataFile.available()) { + /* TODO: it is reading only one byte */ + data = dataFile.read(); + } + dataFile.close(); + interrupts(); + return data; + } else { + dataFile.close(); + return data; + } +} + +uint8_t *to_raw(USBPacket *packet, uint16_t *len) +{ + int i = 0; + uint8_t *msg; + *len = 6 + packet->data_size; + + msg = (uint8_t *)malloc(*len); + + msg[0] = ((packet->command << 5) & 0xE0) + + ((packet->parameters << 1) & 0x1E) + 1; + msg[1] = (packet->cmd_arg1 << 1) + 1; + msg[2] = (packet->cmd_arg2 << 1) + 1; + msg[3] = (packet->data_size >> 7) + 1; + msg[4] = (packet->data_size << 1) + 1; + if (packet->data_size > 0) { + memcpy(&msg[5], packet->data, packet->data_size); + } + msg[5 + packet->data_size] = packet->packet_id << 1; + return msg; +} + +USBPacket *process_packet(uint8_t *msg) +{ + USBPacket *packet = (USBPacket *)malloc(sizeof(*packet)); + packet->command = (msg[0] >> 5) & 0x07; + packet->parameters = (msg[0] >> 1) & 0x0F; + packet->cmd_arg1 = (msg[1] >> 1); + packet->cmd_arg2 = (msg[2] >> 1); + packet->data_size = (msg[4] >> 1) + ((msg[3] & 0xFE) << 6); + if(packet->data_size > 0) { + packet->data = &msg[5]; + } + packet->packet_id = msg[5 + packet->data_size] >> 1; + return packet; +} + +USBPacket *execute_packet(USBPacket *packet) +{ + USBPacket *response; + char data; + char *data_arr; + int pin, num, value, j; + int *int_res = (int *)malloc(sizeof(*int_res)); + + switch(packet->command) { + case BASIC_IO: + /* Command type: Basic I/O */ + pin = packet->cmd_arg1; + switch(packet->parameters) { + case ANALOG_WRITE: + if(IS_PIN_ANALOG(pin)) { + pinMode(pin, OUTPUT); + value = packet->cmd_arg2; + analogWrite(pin, value); + response = usb_ok_packet(packet->packet_id); + } else { + response = usb_error_packet(packet->packet_id, 1); + } + break; + case DIGITAL_WRITE: + if(IS_PIN_DIGITAL(pin)) { + pinMode(pin, OUTPUT); + value = packet->cmd_arg2; + digitalWrite(pin, value); + response = usb_ok_packet(packet->packet_id); + } else { + response = usb_error_packet(packet->packet_id, 1); + } + break; + case ANALOG_READ: + if(IS_PIN_ANALOG(pin)) { + *int_res = analogRead(pin); + response = usb_ok_data_packet(packet->packet_id, + (char *)int_res, sizeof(*int_res)); + } else { + response = usb_error_packet(packet->packet_id, 1); + } + break; + case DIGITAL_READ: + if(IS_PIN_DIGITAL(pin)) { + pinMode(pin, INPUT); + *int_res = digitalRead(pin); + response = usb_ok_data_packet(packet->packet_id, + (char *)int_res, sizeof(*int_res)); + } else { + response = usb_error_packet(packet->packet_id, 1); + } + break; + case TOOGLE_PIN: + pinMode(pin, OUTPUT); + digitalWrite(pin, !digitalRead(pin)); + response = usb_ok_packet(packet->packet_id); + break; + default: + response = usb_error_packet(packet->packet_id, 1); + break; + } + break; + case COMMS: + /* Command type: Serial Communications */ + /* TODO: only reading one byte? */ + num = packet->cmd_arg1; + if(num <= MAX_SERIAL) { + switch(packet->parameters) { + case INIT_UART: + mySerial[num].begin(bitrate[packet->cmd_arg2]); + response = usb_ok_packet(packet->packet_id); + break; + case READ_UART: + data = mySerial[num].read(); + response = usb_ok_data_packet(packet->packet_id, + &data, 1); + break; + case WRITE_UART: + Serial.println("Sending data"); + for(j = 0; j < packet->data_size; j++) { + Serial.write(packet->data[j]); + mySerial[num].write(packet->data[j]); + } + response = usb_ok_packet(packet->packet_id); + break; + case INIT_SPI: + SPI.begin(); + pinMode(10, OUTPUT); + break; + case READ_SPI: + digitalWrite(10, LOW); + data = SPI.transfer(0x00); + response = usb_ok_data_packet(packet->packet_id, + &data, 1); + digitalWrite(10, HIGH); + break; + case WRITE_SPI: + for(j = 0; j < packet->data_size; j++) { + digitalWrite(10, LOW); + SPI.transfer(packet->data[j]); + digitalWrite(10, HIGH); + } + response = usb_ok_packet(packet->packet_id); + break; + case CONFIGURE: + comms.configure(); + response = usb_ok_packet(packet->packet_id); + break; + case TRANSMIT: + comms.tx(packet->data, packet->data_size); + response = usb_ok_packet(packet->packet_id); + break; + case RECEIVE: + char *received; + received=comms.rx(); + if(*received == 1){ + response = usb_ok_data_packet(packet->packet_id, + received+2, *(received + 1)); + }else if(*received == 2){ + response = usb_abort_packet(packet->packet_id); + }else{ + response = usb_error_packet(packet->packet_id,FCS_ERROR); + } + break; + case CHANGE_X: + comms.change_x(packet->cmd_arg1,packet->cmd_arg2); + response = usb_ok_packet(packet->packet_id); + break; + } + } else { + response = usb_error_packet(packet->packet_id, 1); + } + break; + case EVENT: + /* Command type: Events */ + switch(packet->parameters) { + case CONF: + if(packet->data_size > 0) { + event_list[eventCount].bufferid = eventCount; + event_list[eventCount].interval = packet->cmd_arg1; + event_list[eventCount].execute = 0; + event_list[eventCount].action = process_packet(packet->data); + eventCount++; + response = usb_ok_packet(packet->packet_id); + } else { + response = usb_error_packet(packet->packet_id, 1); + } + break; + case DUMP: + Serial.println("Dump event"); + //response = usb_ok_data_packet(dumpData(0), 1); + data = dumpData(packet->cmd_arg1); + response = usb_ok_data_packet(packet->packet_id, &data, 1); + break; + } + break; + case SERVO: + /* Command type: PWM */ + num = packet->cmd_arg1; + value = packet->cmd_arg2; + if(num <= MAX_SERIAL) { + switch(packet->parameters) { + case START: + myServo[num].attach(value); + response = usb_ok_packet(packet->packet_id); + break; + case SET_DC: + myServo[num].write(value); + response = usb_ok_packet(packet->packet_id); + break; + case STOP: + myServo[num].detach(); + response = usb_ok_packet(packet->packet_id); + break; + } + break; + } else { + response = usb_error_packet(packet->packet_id, 1); + } + break; + default: + /* Command type: Unknown */ + response = usb_error_packet(packet->packet_id, 1); + break; + } + return response; +} diff --git a/src/Arduino/abs/abs_comms.cpp b/src/Arduino/abs/abs_comms.cpp new file mode 100644 index 0000000..e5561e6 --- /dev/null +++ b/src/Arduino/abs/abs_comms.cpp @@ -0,0 +1,440 @@ +/*RF implementation: setting up the transceiver AX5042 + * It uses the SPI library + * + * The circuit: + * - Pins 2, 7, 20, 26 of AX5042 connected to 2,5V Power Supply + * - Pins + * - Pin 16 (MISO)of AX5042 connected to MISO (digital pin 50) + * - Pin 17 (MOSI)of AX5042 connected to MOSI (digital pin 51) + * - Pin 15 (CLK) of AX5042 connected to SCK (digital pin 52) + * - Pin 14 (SEL) of AX5042 connected to SS (digital pin 49) + * + * All the programming has be done following the AX5042 Programming Manual +*/ + +#include "abs_comms.h" + +#define CHIP_SELECT_PIN 49 + +/*The next variables save the changes on the default parameters*/ +int frequency; +uint8_t bandsel = BANDSEL; +int bitrate = BITRATE_DEFAULT; +uint8_t modulationValue = 0xFF;//to distinguish it from value 0 +uint8_t tmgcorrfrac = TMGCORRFRAC_DEFAULT; +uint8_t cicdec; +uint32_t fskmul; +uint32_t datarate; + +Comms::Comms() +{ + /*Constructor not used*/ +} + +Comms::~Comms() +{ + /*Destructor not used*/ +} + +/*Setting up the transceiver*/ +void Comms::configure() +{ + pinMode(CHIP_SELECT_PIN, OUTPUT); + SPI.begin(); + write_register(AGCTARGET, 0x0E); + write_register(PLLRNG, (read_register(PLLRNG) | 0x01)); + write_register(RXMISC, ((read_register(RXMISC) | 0x01) & 0xFD));/*write 01 in the last 2 bits*/ + configure_PLLLOOP(BANDSEL); + configure_FREQ(FCARRIER); + configure_TXPWR(); + configure_IFFREQ(); + configure_FSKDEV(BITRATE_DEFAULT); + configure_TXRATE(BITRATE_DEFAULT); + cicdec = configure_CICDEC(BITRATE_DEFAULT); + configure_MODULATION(MOD_DEFAULT); + fskmul = compute_FSKMUL(BITRATE_DEFAULT, TMGCORRFRAC_DEFAULT, MOD_DEFAULT, cicdec); + datarate = configure_DATARATE(BITRATE_DEFAULT, cicdec, fskmul); + //we need the values of fskmul, datarate and tmgcorrfrac for TMGGAIN config + configure_TMGGAIN(fskmul, datarate, TMGCORRFRAC_DEFAULT); + configure_AGCATTACK(BITRATE_DEFAULT, MOD_DEFAULT); + configure_AGCDECAY(BITRATE_DEFAULT, MOD_DEFAULT); + configure_PHASEGAIN(MOD_DEFAULT); + configure_FREQGAIN(MOD_DEFAULT); + configure_FREQGAIN2(); + configure_AMPLGAIN(); + + /*LACKS ENCODING PROGRAMMING*/ + + int fabort = 0; /* '1' to abort packet*/ + byte frmmode = 0b010; /*HDLC*/ + frmmode = frmmode << 1; + byte crcmode = 0b001; /*CRC-16*/ + crcmode = crcmode << 4; + byte framing = crcmode |frmmode | fabort; + write_register(FRAMING, framing); + + write_register(IFMODE, 0x00); /*Frame Mode*/ + + /*IRQ and DCLK control the switches: '00' OFF, '01' Rx, '10' Tx*/ + byte irq_txenz = 0b11011111; + byte dclkz = 0b10111111; + byte pincfg1 = read_register(PINCFG1); + pincfg1 = pincfg1 & dclkz & irq_txenz; + write_register(PINCFG1, pincfg1); + + byte pincfg2 = 0b01110110; + write_register(PINCFG2, pincfg2); +} + +void Comms::tx(uint8_t *data,int data_size) +{ + write_register(PWRMODE, 0x60); + delay (3); + if(frequency == NULL) { + configure_FREQ(FCARRIER); + } else { + configure_FREQ(frequency); + } + + /*LACKS ENCODING*/ + + write_register(PWRMODE, 0x6C); + delay (0.05); + auto_ranging(); + write_register(PWRMODE, 0x6D); + delay (0.05); + hdlc_tx(data, data_size); + write_register(PWRMODE, 0x00); + +} + +char* Comms::rx() +{ + write_register(PWRMODE, 0x60); + delay(3); + if(frequency == 0) { + configure_FREQ(FCARRIER); + } else { + configure_FREQ(frequency); + } + + /*LACKS ENCODING*/ + + write_register(PWRMODE, 0x68); + delay(0.05); + auto_ranging(); + write_register(PWRMODE, 0x69); + delay(0.05); + char *data = hdlc_rx(); + write_register(PWRMODE, 0x00); + return data; +} + +/*It has to be specified to the HWmod_comms. Parameters defined in comms.h*/ +void Comms::change_x(int parameter, int value) +{ + switch(parameter) { + case FREQUENCY: + /*We expect the value to be 1(433) or 0(915)*/ + if(value == 0 || value == 1) { + frequency = (((1 - value) * 915) + (value * 433)) * pow(10, 6); + configure_FREQ(frequency); + configure_PLLLOOP(value); + bandsel = value; + } + break; + case BITRATE: + configure_FSKDEV(value); + configure_TXRATE(value); + cicdec = configure_CICDEC(value); + if(modulationValue == 0xFF) { + fskmul = compute_FSKMUL(value, tmgcorrfrac, MOD_DEFAULT, cicdec); + } else { + fskmul = compute_FSKMUL(value, tmgcorrfrac, modulationValue, cicdec); + } + datarate = configure_DATARATE(value, cicdec, fskmul); + configure_TMGGAIN(fskmul, datarate, tmgcorrfrac); + configure_AGCATTACK(bitrate, value); //check if put bitrate or another variable here + configure_AGCDECAY(bitrate, value); //same check here + bitrate = value; + break; + + case MODULATION_TYPE: + configure_MODULATION(value); + fskmul = compute_FSKMUL(bitrate, tmgcorrfrac, value, cicdec); + datarate = configure_DATARATE(bitrate, cicdec, fskmul); + configure_TMGGAIN(fskmul, datarate, tmgcorrfrac); + configure_AGCATTACK(bitrate, value); + configure_AGCDECAY(bitrate, value); + configure_PHASEGAIN(value); + configure_FREQGAIN(value); + modulationValue = value; + break; + + case TMRECOV: + uint8_t modulation; + if(modulationValue == 0xFF) { + modulation = MOD_DEFAULT; + } else { + modulation = modulationValue; + } + fskmul = compute_FSKMUL(bitrate, value, modulation, cicdec); + datarate = configure_DATARATE(bitrate, cicdec, fskmul); + configure_TMGGAIN(fskmul, datarate, value); + configure_AGCATTACK(bitrate, modulation); + configure_AGCDECAY(bitrate, modulation); + configure_PHASEGAIN(modulation); + configure_FREQGAIN(modulation); + tmgcorrfrac = value; + break; + //default : + /*Parameter not changeable*/ + } +} + +/*Read a register*/ +unsigned int Comms::read_register(byte this_register) +{ + unsigned int result = 0; + byte reading = 0b01111111; + byte data_to_send = reading & this_register; + Serial.println(this_register, BIN); + digitalWrite(CHIP_SELECT_PIN, LOW); + SPI.transfer(data_to_send); + result = SPI.transfer(0x00); + digitalWrite(CHIP_SELECT_PIN, HIGH); + return (result); +} + +/*Function to write a determined value in a determined Register*/ +void Comms::write_register(byte this_register, byte this_value) +{ + byte writing = 0b10000000; + byte data_to_send = writing | this_register; + digitalWrite(CHIP_SELECT_PIN, LOW); + SPI.transfer(data_to_send); + SPI.transfer(this_value); + digitalWrite(CHIP_SELECT_PIN, HIGH); +} + +/*Auto range needed after initialize or setting chip in SYNTHRX or SYNTHTX*/ +void Comms::auto_ranging() +{ + write_register(PLLRANGING, 0x08); +} + +/*------------------CONFIGURATION FUNCTIONS---------------------*/ +/*This function configures register PLLLOOP*/ +void Comms::configure_PLLLOOP(int band) +{ + band = band << 5; + byte pllloop = band | 0b00001111; + write_register(PLLLOOP, pllloop); +} + +/*The parameter "freq" is supposed to be in Hz. + *This function configures registers FREQ3, FREQ2, + *FREQ1, FREQ0 + */ +void Comms::configure_FREQ(int fcarrier) +{ + uint8_t freq0; + uint32_t freq = ((fcarrier / FXTAL) * pow(2,24)) + 1 / 2; + freq0 = freq >> 24; + write_register(FREQ3, freq0); + freq0 = freq >> 16; + write_register(FREQ2, freq0); + freq0 = freq >> 8; + write_register(FREQ1, freq0); + freq0 = freq; + write_register(FREQ0, freq0); +} + +/*This function configures register TXPWR*/ +void Comms::configure_TXPWR() +{ + write_register(TXPWR, 0x0F); +} + +/*This function configures register IFFREQHI, IFFREQLO*/ +void Comms::configure_IFFREQ() +{ + uint8_t iffreq0; + uint32_t iffreq = ((FIF / FXTAL) * pow(2,17)) + 1 / 2; + iffreq0 = iffreq >> 8; + write_register(IFFREQHI, iffreq0); + iffreq0 = iffreq; + write_register(IFFREQLO, iffreq0); +} + +/*This function configures registers FSKDEV2, FSKDEV1, +*FSKDEV0*/ +void Comms::configure_FSKDEV(int bitrate) +{ + int fdev = (H / 2) * bitrate; + uint8_t fsk0; + uint32_t fsk = ((fdev / FXTAL) * pow(2,24)) + 1 / 2; + fsk0 = fsk >> 16; + write_register(FSKDEV2, fsk0); + fsk0 = fsk >> 8; + write_register(FSKDEV1, fsk0); + fsk0 = fsk; + write_register(FSKDEV0, fsk0); +} + +/*This function configures registers TXRATEHI, TXRATEMID, +*TXRATELO*/ +void Comms::configure_TXRATE(int bitrate) +{ + uint8_t txr0; + uint32_t txr = ((bitrate / FXTAL) * pow(2,24)) + 1/2; + txr0 = txr >> 16; + write_register(TXRATEHI, txr0); + txr0 = txr >> 8; + write_register(TXRATEMID, txr0); + txr0 = txr; + write_register(TXRATELO, txr0); +} + +/*This function configures registers CICDECHI, CICDECLO*/ +uint32_t Comms::configure_CICDEC(int bitrate) +{ + uint8_t cicdec0; + uint32_t cicdec = (1.5 * FXTAL) / (8 * 1.2 * (1 + H) * bitrate); + cicdec0 = cicdec >> 8; + write_register(CICDECHI, cicdec0); + cicdec0 = cicdec; + write_register(CICDECLO, cicdec0); + return cicdec; +} + +/*This function configures register MODULATION*/ +void Comms::configure_MODULATION(int modulation) +{ + uint8_t modValue = getModulationReg(modulation); + write_register(MODULATION, modValue); +} + +/*This function configures register FSKMUL*/ +uint32_t Comms::compute_FSKMUL(int bitrate, uint8_t tmgcorrfrac, uint8_t modValue, uint32_t cicdec) +{ + if(getModulationReg(modValue) < 8) { + fskmul = 1; + } else { + unsigned int comprovacion = FXTAL / (4 * bitrate * cicdec); + if(tmgcorrfrac >= comprovacion) { + fskmul = 1 / (4 * bitrate * (cicdec / FXTAL) + (1 / tmgcorrfrac)); + } + } + return fskmul; +} + +/*This function configures register DATARATE*/ +uint32_t Comms::configure_DATARATE(int bitrate, int cicdec, int fskmul) +{ + uint8_t datarate0; + datarate = pow(2,10) * (FXTAL / (cicdec * fskmul * bitrate)) + 1 / 2; + datarate0 = datarate >> 8; + write_register(DATARATEHI, datarate0); + datarate0 = datarate; + write_register(DATARATELO, datarate0); + return datarate; +} + +/*This function configures registers TMGGAINHI, TMGGAINLO*/ +void Comms::configure_TMGGAIN(uint32_t fskmul,uint32_t datarate,int tmgcorrfrac) +{ + uint8_t tmggain0; + uint32_t tmggain = fskmul * (datarate/tmgcorrfrac) + 1/2; + tmggain0 = tmggain >> 8; + write_register(TMGGAINHI, tmggain0); + tmggain0 = tmggain; + write_register(TMGGAINLO, tmggain0); +} + +/*This function configures registers AGCATTACK*/ +void Comms::configure_AGCATTACK(int bitrate, uint8_t modValue) +{ + uint8_t agcattack; + if(modValue == 0) { + /*log2(x) = log(x)/log(2)*/ + agcattack = 27 + log(bitrate / (10 * FXTAL)) / log(2); + } else { + agcattack = 27 + log(bitrate / FXTAL) / log(2); + } + write_register(AGCATTACK, agcattack); +} + +/*This function configures registers AGCDECAY*/ +void Comms::configure_AGCDECAY(int bitrate, uint8_t modValue ) +{ + uint8_t agcdecay; + if(modValue == 0) { + agcdecay = 27 + log(bitrate / (100 * FXTAL)) / log(2); + } else { + agcdecay = 27 + log(bitrate / (10 * FXTAL)) / log(2); + } + write_register(AGCDECAY, agcdecay); +} + +/*This function configures registers PHASEGAIN*/ +void Comms::configure_PHASEGAIN(uint8_t modValue) +{ + if(modValue == 0) { + write_register(PHASEGAIN, 0x00); + } else { + write_register(PHASEGAIN, 0x03); + } +} + +/*This function configures registers FREQGAIN*/ +void Comms::configure_FREQGAIN(uint8_t modValue) +{ + if(modValue < 7) { + write_register(FREQGAIN, 0x06); + } else { + write_register(FREQGAIN, 0x03); + } +} + +/*This function configures registers FREQGAIN2*/ +void Comms::configure_FREQGAIN2() +{ + write_register(FREQGAIN2, 0x06); +} + +/*This function configures registers AMPLGAIN*/ +void Comms::configure_AMPLGAIN() +{ + write_register(AMPLGAIN, 0x06); +} + +/*--------------------------------------------------------------*/ + +/*This function translates the String modulation into the value to be assigned +*to the register in hexadecimal*/ +uint8_t Comms::getModulationReg(int modulation) +{ + uint8_t modValue; + switch (modulation){ + case ASK: + modValue = 0x00; + break; + case PSK: + modValue = 0x04; + break; + case OQPSK: + modValue = 0x06; + break; + case MSK: + modValue = 0x07; + break; + case FSK: + modValue = 0x0B; + break; + case GFSK: + modValue = 0x0F; + break; + } + return modValue; +} diff --git a/src/Arduino/abs/abs_comms.h b/src/Arduino/abs/abs_comms.h new file mode 100644 index 0000000..0d28be4 --- /dev/null +++ b/src/Arduino/abs/abs_comms.h @@ -0,0 +1,136 @@ +/* AX5042 library for Arduino */ + +#ifndef _COMMS_H +#define _COMMS_H + +#include "Arduino.h" +#include /* For communication via SPI. */ +#include "abs_hdlc.h" + +class Comms; +class Comms +{ + public: + Comms();/*Constructor not used*/ + ~Comms();/*Destructor not used*/ + void configure(); + void tx(uint8_t *data, int data_size); + char *rx(); + void change_x(int parameter, int value); + unsigned int read_register(byte this_register); + void write_register(byte this_register, byte this_value); + private: + void auto_ranging(); + void configure_PLLLOOP(int band); + void configure_FREQ(int fcarrier); + void configure_TXPWR(); + void configure_IFFREQ(); + void configure_FSKDEV(int bitrate); + void configure_TXRATE(int bitrate); + uint32_t configure_CICDEC(int bitrate); + void configure_MODULATION(int modulation); + uint32_t compute_FSKMUL(int bitrate, uint8_t tmgcorrfrac, uint8_t modValue, uint32_t cicdec); + uint32_t configure_DATARATE(int bitrate, int cicdec, int fskmul); + void configure_TMGGAIN(uint32_t fskmul, uint32_t datarate, int tmgcorrfrac); + void configure_AGCATTACK(int bitrate, uint8_t modValue); + void configure_AGCDECAY(int bitrate, uint8_t modValue); + void configure_PHASEGAIN(uint8_t modValue); + void configure_FREQGAIN(uint8_t modValue); + void configure_FREQGAIN2(); + void configure_AMPLGAIN(); + uint8_t getModulationReg(int modulation); +}; + +/* REGISTERS DECLARATION */ + +#define REVISION 0x00 +#define SCRATCH 0x01 +#define PWRMODE 0x02 +#define XTALOSC 0x03 +#define FIFOCTRL 0x04 +#define FIFODATA 0x05 +#define IRQMASK 0x06 +#define IRQREQUEST 0x07 +#define IFMODE 0x08 +#define PINCFG1 0x0C +#define PINCFG2 0x0D +#define PINCFG3 0x0E +#define IRQINVERSION 0x0F +#define MODULATION 0x10 +#define ENCODING 0x11 +#define FRAMING 0x12 +#define CRCINIT3 0x14 +#define CRCINIT2 0x15 +#define CRCINIT1 0x16 +#define CRCINIT0 0x17 +#define FREQ3 0x20 +#define FREQ2 0x21 +#define FREQ1 0x22 +#define FREQ0 0x23 +#define FSKDEV2 0x25 +#define FSKDEV1 0x26 +#define FSKDEV0 0x27 +#define IFFREQHI 0x28 +#define IFFREQLO 0x29 +#define PLLLOOP 0x2C +#define PLLRANGING 0x2D +#define TXPWR 0x30 +#define TXRATEHI 0x31 +#define TXRATEMID 0x32 +#define TXRATELO 0x33 +#define MODMISC 0x34 +#define AGCTARGET 0x39 +#define AGCATTACK 0x3A +#define AGCDECAY 0x3B +#define AGCCOUNTER 0x3C +#define CICSHIFT 0x3E +#define CICDECHI 0x3E +#define CICDECLO 0x3F +#define DATARATEHI 0x40 +#define DATARATELO 0x41 +#define TMGGAINHI 0x42 +#define TMGGAINLO 0x43 +#define PHASEGAIN 0x44 +#define FREQGAIN 0x45 +#define FREQGAIN2 0x46 +#define AMPLGAIN 0x47 +#define TRKAMPLHI 0x48 +#define TRKAMPLLO 0x49 +#define TRKPHASEHI 0x4A +#define TRKPHASELO 0x4B +#define TRKFREQHI 0x4C +#define TRKFREQLO 0x4D +#define APEOVER 0x70 +#define PLLVCOI 0x72 +#define PLLRNG 0x74 +#define REF 0x7C +#define RXMISC 0x7D + +/*Parameters declaration*/ + +#define BITRATE_DEFAULT 100000 +#define FCARRIER 433000000 +#define FIF 1000000 +#define FXTAL 16300000 +#define H 0.5 +#define TMGCORRFRAC_DEFAULT 32 +#define MOD_DEFAULT 4 +#define BANDSEL 1 + +typedef enum { + FREQUENCY, + BITRATE, + MODULATION_TYPE, + TMRECOV +} VariablesChangeX; + +typedef enum { + ASK, + PSK, + OQPSK, + MSK, + FSK, + GFSK +} ModulationTypes; + +#endif diff --git a/src/Arduino/abs/abs_hdlc.cpp b/src/Arduino/abs/abs_hdlc.cpp new file mode 100644 index 0000000..dd067de --- /dev/null +++ b/src/Arduino/abs/abs_hdlc.cpp @@ -0,0 +1,120 @@ +/* + * RECEPTION RUTINE + * Following HDLC Receive Flow Chart from AXSEM AX5042 Programming Manual (page 32) + */ +#include "abs_hdlc.h" + +Comms coms; + +char *hdlc_rx() +{ + char *response; + char data_size; + int received; + int i = 2; + unsigned int control; + unsigned int data; + control = coms.read_register(FIFOCTRL); + data = coms.read_register(FIFODATA); + while(control & (bit(1) | bit(0)) != 0x01) { // Search for delimiter + control = coms.read_register(FIFOCTRL); + data = coms.read_register(FIFODATA); + } + received = 0; + while(received == 0) { + control = coms.read_register(FIFOCTRL); + data = coms.read_register(FIFODATA); + if(control & bit(0) == bit(0)) { + *response = 2; + received = 1; + /*DISCARDED PACKAGE: Abort detected*/ + } else if(control & bit(1) == bit(1)) { + if(data & bit(3) == bit(3)) { + if(data & (bit(2) | bit(1) | bit(0)) == 0x06) { + received = 1; + data_size = i - 2;/*The last two frames are of CRC, we must delete them.*/ + *response = 0; + *(response + 1) = data_size; + /*CRC OK: end of packet*/ + } else { + received = 0; + i = 2; /*We reset the counter to 2, pointing at the first data position*/ + /*DISCARDED PACKAGE: Number of packet bits not divisible by 8*/ + } + } else { + received = 1; + *response = 1; + /*DISCARDED PACKAGE: wrong CRC + *We will notify the HWDmods of this reception */ + } + } else { + received = 0; + *(response + i) = data; + i++; + /*DATA FRAME: save it to data buffer*/ + } + } + return response; +} + + +/* + * TRANSMITION RUTINE + * Following HDLC transmit Flow Chart from AXSEM AX5042 Programming Manual (page 31) + */ + +void send_preamble() +{ + int i = 0; + unsigned int control = 0x03; + unsigned int data = 0xAA; + while(i < 10) { + coms.write_register(FIFOCTRL, control); + coms.write_register(FIFODATA, data); + i++; + } +} + +void send_packet(uint8_t * data, int data_size) +{ + int i = 0; + + /*HDLC FLAG, PACKET DELIMITER*/ + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0x7E); + + for(i = 0; i < data_size; i++) { + coms.write_register(FIFOCTRL, 0x00); + coms.write_register(FIFODATA, data[i]); + } + + /*CRC*/ + coms.write_register(FIFOCTRL, 0x01); + coms.write_register(FIFODATA, 0x00); + coms.write_register(FIFOCTRL, 0x01); + coms.write_register(FIFODATA, 0x00); + + /*HDLC FLAG, PACKET DELIMITER*/ + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0x7E); + +} + +void send_ABORT() +{ + //HDLC ABORT + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0xFF); + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0xFF); +} + +void hdlc_tx(uint8_t *data, int data_size) +{ + send_preamble(); + + send_packet(data,data_size); + + send_ABORT(); +} + diff --git a/src/Arduino/abs/abs_hdlc.h b/src/Arduino/abs/abs_hdlc.h new file mode 100644 index 0000000..bd349db --- /dev/null +++ b/src/Arduino/abs/abs_hdlc.h @@ -0,0 +1,15 @@ + +#ifndef _HDLC_H +#define _HDLC_H + +#include "Arduino.h" +#include /* For communication via SPI. */ +#include "abs_comms.h" + +char *hdlc_rx(); +void send_preamble(); +void send_packet(char *data, int data_size); +void send_ABORT(); +void hdlc_tx(uint8_t *data, int data_size); + +#endif diff --git a/src/Arduino/abs_test/abs.h b/src/Arduino/abs_test/abs.h new file mode 100644 index 0000000..363f6cb --- /dev/null +++ b/src/Arduino/abs_test/abs.h @@ -0,0 +1,92 @@ +#ifndef __ABS_H +#define __ABS_H + +#include "Arduino.h" + +#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 40) +#define IS_PIN_ANALOG(p) ((p) >= 0 && (p) <= 15) +#define IS_PIN_PWM(p) digitalPinHasPWM(p) + +#define MAX_SERVO 2 +#define MAX_SERIAL 2 +#define MAX_EVENTS 10 +#define MAX_PACKET_SIZE 2 * 1024 +#define SD_CS 52 +#define COMMS_CS 49 +#define TIMER_INTERVAL 500000 +#define SERIAL_BITRATE 115200 +const long bitrate[] = {300, 1200, 2400, 4800, 9600, 14400, + 19200, 28800, 38400, 57600, 115200}; + +typedef struct { + int command; + int parameters; + int cmd_arg1; + int cmd_arg2; + int data_size; + uint8_t *data; + int packet_id; + } USBPacket; + +typedef struct { + int bufferid; + int interval; + int execute; + USBPacket *action; +} Event; + +typedef enum { + CONTROL, + BASIC_IO, + COMMS, + EVENT, + SERVO +} Command; + +typedef enum { + OK, + OK_DATA, + ERRORS, + ABORT +} ParametersControl; + +typedef enum { + ANALOG_WRITE, + DIGITAL_WRITE, + ANALOG_READ, + DIGITAL_READ, + TOOGLE_PIN +} ParametersBasicIO; + +typedef enum { + INIT_UART, + READ_UART, + WRITE_UART, + INIT_SPI, + READ_SPI, + WRITE_SPI, + INIT_CAN, + READ_CAN, + WRITE_CAN, + CONFIGURE, + TRANSMIT, + RECEIVE, + CHANGE_X +} ParametersComms; + +typedef enum { + CONF, + DUMP +} ParametersEvents; + +typedef enum { + START, + SET_DC, + STOP +} ParametersServo; + +typedef enum { + FCS_ERROR +} Errors; + +#endif diff --git a/src/Arduino/abs_test/abs.ino b/src/Arduino/abs_test/abs.ino new file mode 100644 index 0000000..4ec0c04 --- /dev/null +++ b/src/Arduino/abs_test/abs.ino @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "abs.h" +#include +#include + +Comms comms; + +Servo myServo[MAX_SERVO]; +SoftwareSerial mySerial[MAX_SERIAL] = {SoftwareSerial(10,11), SoftwareSerial(7,8)}; + +File buffer; +USB Usb; +Event event_list[MAX_EVENTS]; +int time = 0, eventCount = 0, packetCount = 0; + +ADK adk(&Usb, "UPC, BarcelonaTech", + "Android Beyond the Stratoshpere", + "Android Beyond the Stratoshpere", + "1.0", + "http://www.upc.edu", + "000000000000000001"); + +void reboot(void) +{ + wdt_enable(WDTO_15MS); + while(1); +} + +void setup(void) +{ + Serial.begin(SERIAL_BITRATE); + Serial.println("\r\nArduino firmware start"); + + if(Usb.Init() == -1) { + Serial.println("OSCOKIRQ failed to assert"); + while(Usb.Init() == -1); /* retry */ + } + + Timer1.initialize(TIMER_INTERVAL); + Timer1.pwm(9, 512); + Timer1.attachInterrupt(events_routine); + + pinMode(SD_CS, OUTPUT); + + if (!SD.begin(SD_CS)) { + Serial.println("Error initializing SDcard"); + } + + Serial.println("Setup Ok\n"); +} + +void loop(void) +{ + USBPacket *packet; + USBPacket *pkt_res; + uint8_t *response; + uint8_t msg[MAX_PACKET_SIZE]; + int i = 0; + char str[80]; + uint8_t ret; + uint16_t len; + + Usb.Task(); + + if(!adk.isReady()) { + Serial.println("ADK not ready\n"); + return; + } + + len = sizeof(msg); + adk.RcvData(&len, msg); + if(len > 0) { + packet = process_packet(msg); + + sprintf(str, "Received %d %d:%d %d:%d:%d", packet->packet_id, + packet->command, packet->parameters, packet->cmd_arg1, + packet->cmd_arg2, packet->data_size); + Serial.println(str); + + pkt_res = execute_packet(packet); + free(packet); + + sprintf(str, "Result %d %d:%d %d:%d:%d", pkt_res->packet_id, + pkt_res->command, pkt_res->parameters, pkt_res->cmd_arg1, + pkt_res->cmd_arg2, pkt_res->data_size); + Serial.println(str); + + response = to_raw(pkt_res, &len); + free(pkt_res); + + adk.SndData(len, response); + free(response); + } + + for(i = 0; i < eventCount; i++) { + if(event_list[i].execute == 1) { + pkt_res = execute_packet(event_list[i].action); + save_event_data(i, pkt_res); + free(pkt_res); + event_list[i].execute = 0; + } + } +} + +void events_routine(void) +{ + int i = 0; + for(i = 0; i < eventCount; i++) { + if(time % event_list[i].interval == 0) { + Serial.println("Event!!!"); + event_list[i].execute = 1; + } + } + time++; +} diff --git a/src/Arduino/abs/assets.ino b/src/Arduino/abs_test/assets.ino similarity index 100% rename from src/Arduino/abs/assets.ino rename to src/Arduino/abs_test/assets.ino diff --git a/src/Arduino/comms_test/comms.cpp b/src/Arduino/comms_test/comms.cpp new file mode 100644 index 0000000..72fa4bc --- /dev/null +++ b/src/Arduino/comms_test/comms.cpp @@ -0,0 +1,440 @@ +/*RF implementation: setting up the transceiver AX5042 + * It uses the SPI library + * + * The circuit: + * - Pins 2, 7, 20, 26 of AX5042 connected to 2,5V Power Supply + * - Pins + * - Pin 16 (MISO)of AX5042 connected to MISO (digital pin 50) + * - Pin 17 (MOSI)of AX5042 connected to MOSI (digital pin 51) + * - Pin 15 (CLK) of AX5042 connected to SCK (digital pin 52) + * - Pin 14 (SEL) of AX5042 connected to SS (digital pin 49) + * + * All the programming has be done following the AX5042 Programming Manual +*/ + +#include "comms.h" + +#define CHIP_SELECT_PIN 49 + +/*The next variables save the changes on the default parameters*/ +int frequency; +uint8_t bandsel = BANDSEL; +int bitrate = BITRATE_DEFAULT; +uint8_t modulationValue = 0xFF;//to distinguish it from value 0 +uint8_t tmgcorrfrac = TMGCORRFRAC_DEFAULT; +uint8_t cicdec; +uint32_t fskmul; +uint32_t datarate; + +Comms::Comms() +{ + /*Constructor not used*/ +} + +Comms::~Comms() +{ + /*Destructor not used*/ +} + +/*Setting up the transceiver*/ +void Comms::configure() +{ + pinMode(CHIP_SELECT_PIN, OUTPUT); + SPI.begin(); + write_register(AGCTARGET, 0x0E); + write_register(PLLRNG, (read_register(PLLRNG) | 0x01)); + write_register(RXMISC, ((read_register(RXMISC) | 0x01) & 0xFD));/*write 01 in the last 2 bits*/ + configure_PLLLOOP(BANDSEL); + configure_FREQ(FCARRIER); + configure_TXPWR(); + configure_IFFREQ(); + configure_FSKDEV(BITRATE_DEFAULT); + configure_TXRATE(BITRATE_DEFAULT); + cicdec = configure_CICDEC(BITRATE_DEFAULT); + configure_MODULATION(MOD_DEFAULT); + fskmul = compute_FSKMUL(BITRATE_DEFAULT, TMGCORRFRAC_DEFAULT, MOD_DEFAULT, cicdec); + datarate = configure_DATARATE(BITRATE_DEFAULT, cicdec, fskmul); + //we need the values of fskmul, datarate and tmgcorrfrac for TMGGAIN config + configure_TMGGAIN(fskmul, datarate, TMGCORRFRAC_DEFAULT); + configure_AGCATTACK(BITRATE_DEFAULT, MOD_DEFAULT); + configure_AGCDECAY(BITRATE_DEFAULT, MOD_DEFAULT); + configure_PHASEGAIN(MOD_DEFAULT); + configure_FREQGAIN(MOD_DEFAULT); + configure_FREQGAIN2(); + configure_AMPLGAIN(); + + /*LACKS ENCODING PROGRAMMING*/ + + int fabort = 0; /* '1' to abort packet*/ + byte frmmode = 0b010; /*HDLC*/ + frmmode = frmmode << 1; + byte crcmode = 0b001; /*CRC-16*/ + crcmode = crcmode << 4; + byte framing = crcmode |frmmode | fabort; + write_register(FRAMING, framing); + + write_register(IFMODE, 0x00); /*Frame Mode*/ + + /*IRQ and DCLK control the switches: '00' OFF, '01' Rx, '10' Tx*/ + byte irq_txenz = 0b11011111; + byte dclkz = 0b10111111; + byte pincfg1 = read_register(PINCFG1); + pincfg1 = pincfg1 & dclkz & irq_txenz; + write_register(PINCFG1, pincfg1); + + byte pincfg2 = 0b01110110; + write_register(PINCFG2, pincfg2); +} + +void Comms::tx(uint8_t *data,int data_size) +{ + write_register(PWRMODE, 0x60); + delay (3); + if(frequency == NULL) { + configure_FREQ(FCARRIER); + } else { + configure_FREQ(frequency); + } + + /*LACKS ENCODING*/ + + write_register(PWRMODE, 0x6C); + delay (0.05); + auto_ranging(); + write_register(PWRMODE, 0x6D); + delay (0.05); + hdlc_tx(data, data_size); + write_register(PWRMODE, 0x00); + +} + +char* Comms::rx() +{ + write_register(PWRMODE, 0x60); + delay(3); + if(frequency == 0) { + configure_FREQ(FCARRIER); + } else { + configure_FREQ(frequency); + } + + /*LACKS ENCODING*/ + + write_register(PWRMODE, 0x68); + delay(0.05); + auto_ranging(); + write_register(PWRMODE, 0x69); + delay(0.05); + char *data = hdlc_rx(); + write_register(PWRMODE, 0x00); + return data; +} + +/*It has to be specified to the HWmod_comms. Parameters defined in comms.h*/ +void Comms::change_x(int parameter, int value) +{ + switch(parameter) { + case FREQUENCY: + /*We expect the value to be 1(433) or 0(915)*/ + if(value == 0 || value == 1) { + frequency = (((1 - value) * 915) + (value * 433)) * pow(10, 6); + configure_FREQ(frequency); + configure_PLLLOOP(value); + bandsel = value; + } + break; + case BITRATE: + configure_FSKDEV(value); + configure_TXRATE(value); + cicdec = configure_CICDEC(value); + if(modulationValue == 0xFF) { + fskmul = compute_FSKMUL(value, tmgcorrfrac, MOD_DEFAULT, cicdec); + } else { + fskmul = compute_FSKMUL(value, tmgcorrfrac, modulationValue, cicdec); + } + datarate = configure_DATARATE(value, cicdec, fskmul); + configure_TMGGAIN(fskmul, datarate, tmgcorrfrac); + configure_AGCATTACK(bitrate, value); //check if put bitrate or another variable here + configure_AGCDECAY(bitrate, value); //same check here + bitrate = value; + break; + + case MODULATION_TYPE: + configure_MODULATION(value); + fskmul = compute_FSKMUL(bitrate, tmgcorrfrac, value, cicdec); + datarate = configure_DATARATE(bitrate, cicdec, fskmul); + configure_TMGGAIN(fskmul, datarate, tmgcorrfrac); + configure_AGCATTACK(bitrate, value); + configure_AGCDECAY(bitrate, value); + configure_PHASEGAIN(value); + configure_FREQGAIN(value); + modulationValue = value; + break; + + case TMRECOV: + uint8_t modulation; + if(modulationValue == 0xFF) { + modulation = MOD_DEFAULT; + } else { + modulation = modulationValue; + } + fskmul = compute_FSKMUL(bitrate, value, modulation, cicdec); + datarate = configure_DATARATE(bitrate, cicdec, fskmul); + configure_TMGGAIN(fskmul, datarate, value); + configure_AGCATTACK(bitrate, modulation); + configure_AGCDECAY(bitrate, modulation); + configure_PHASEGAIN(modulation); + configure_FREQGAIN(modulation); + tmgcorrfrac = value; + break; + //default : + /*Parameter not changeable*/ + } +} + +/*Read a register*/ +unsigned int Comms::read_register(byte this_register) +{ + unsigned int result = 0; + byte reading = 0b01111111; + byte data_to_send = reading & this_register; + Serial.println(this_register, BIN); + digitalWrite(CHIP_SELECT_PIN, LOW); + SPI.transfer(data_to_send); + result = SPI.transfer(0x00); + digitalWrite(CHIP_SELECT_PIN, HIGH); + return (result); +} + +/*Function to write a determined value in a determined Register*/ +void Comms::write_register(byte this_register, byte this_value) +{ + byte writing = 0b10000000; + byte data_to_send = writing | this_register; + digitalWrite(CHIP_SELECT_PIN, LOW); + SPI.transfer(data_to_send); + SPI.transfer(this_value); + digitalWrite(CHIP_SELECT_PIN, HIGH); +} + +/*Auto range needed after initialize or setting chip in SYNTHRX or SYNTHTX*/ +void Comms::auto_ranging() +{ + write_register(PLLRANGING, 0x08); +} + +/*------------------CONFIGURATION FUNCTIONS---------------------*/ +/*This function configures register PLLLOOP*/ +void Comms::configure_PLLLOOP(int band) +{ + band = band << 5; + byte pllloop = band | 0b00001111; + write_register(PLLLOOP, pllloop); +} + +/*The parameter "freq" is supposed to be in Hz. + *This function configures registers FREQ3, FREQ2, + *FREQ1, FREQ0 + */ +void Comms::configure_FREQ(int fcarrier) +{ + uint8_t freq0; + uint32_t freq = ((fcarrier / FXTAL) * pow(2,24)) + 1 / 2; + freq0 = freq >> 24; + write_register(FREQ3, freq0); + freq0 = freq >> 16; + write_register(FREQ2, freq0); + freq0 = freq >> 8; + write_register(FREQ1, freq0); + freq0 = freq; + write_register(FREQ0, freq0); +} + +/*This function configures register TXPWR*/ +void Comms::configure_TXPWR() +{ + write_register(TXPWR, 0x0F); +} + +/*This function configures register IFFREQHI, IFFREQLO*/ +void Comms::configure_IFFREQ() +{ + uint8_t iffreq0; + uint32_t iffreq = ((FIF / FXTAL) * pow(2,17)) + 1 / 2; + iffreq0 = iffreq >> 8; + write_register(IFFREQHI, iffreq0); + iffreq0 = iffreq; + write_register(IFFREQLO, iffreq0); +} + +/*This function configures registers FSKDEV2, FSKDEV1, +*FSKDEV0*/ +void Comms::configure_FSKDEV(int bitrate) +{ + int fdev = (H / 2) * bitrate; + uint8_t fsk0; + uint32_t fsk = ((fdev / FXTAL) * pow(2,24)) + 1 / 2; + fsk0 = fsk >> 16; + write_register(FSKDEV2, fsk0); + fsk0 = fsk >> 8; + write_register(FSKDEV1, fsk0); + fsk0 = fsk; + write_register(FSKDEV0, fsk0); +} + +/*This function configures registers TXRATEHI, TXRATEMID, +*TXRATELO*/ +void Comms::configure_TXRATE(int bitrate) +{ + uint8_t txr0; + uint32_t txr = ((bitrate / FXTAL) * pow(2,24)) + 1/2; + txr0 = txr >> 16; + write_register(TXRATEHI, txr0); + txr0 = txr >> 8; + write_register(TXRATEMID, txr0); + txr0 = txr; + write_register(TXRATELO, txr0); +} + +/*This function configures registers CICDECHI, CICDECLO*/ +uint32_t Comms::configure_CICDEC(int bitrate) +{ + uint8_t cicdec0; + uint32_t cicdec = (1.5 * FXTAL) / (8 * 1.2 * (1 + H) * bitrate); + cicdec0 = cicdec >> 8; + write_register(CICDECHI, cicdec0); + cicdec0 = cicdec; + write_register(CICDECLO, cicdec0); + return cicdec; +} + +/*This function configures register MODULATION*/ +void Comms::configure_MODULATION(int modulation) +{ + uint8_t modValue = getModulationReg(modulation); + write_register(MODULATION, modValue); +} + +/*This function configures register FSKMUL*/ +uint32_t Comms::compute_FSKMUL(int bitrate, uint8_t tmgcorrfrac, uint8_t modValue, uint32_t cicdec) +{ + if(getModulationReg(modValue) < 8) { + fskmul = 1; + } else { + unsigned int comprovacion = FXTAL / (4 * bitrate * cicdec); + if(tmgcorrfrac >= comprovacion) { + fskmul = 1 / (4 * bitrate * (cicdec / FXTAL) + (1 / tmgcorrfrac)); + } + } + return fskmul; +} + +/*This function configures register DATARATE*/ +uint32_t Comms::configure_DATARATE(int bitrate, int cicdec, int fskmul) +{ + uint8_t datarate0; + datarate = pow(2,10) * (FXTAL / (cicdec * fskmul * bitrate)) + 1 / 2; + datarate0 = datarate >> 8; + write_register(DATARATEHI, datarate0); + datarate0 = datarate; + write_register(DATARATELO, datarate0); + return datarate; +} + +/*This function configures registers TMGGAINHI, TMGGAINLO*/ +void Comms::configure_TMGGAIN(uint32_t fskmul,uint32_t datarate,int tmgcorrfrac) +{ + uint8_t tmggain0; + uint32_t tmggain = fskmul * (datarate/tmgcorrfrac) + 1/2; + tmggain0 = tmggain >> 8; + write_register(TMGGAINHI, tmggain0); + tmggain0 = tmggain; + write_register(TMGGAINLO, tmggain0); +} + +/*This function configures registers AGCATTACK*/ +void Comms::configure_AGCATTACK(int bitrate, uint8_t modValue) +{ + uint8_t agcattack; + if(modValue == 0) { + /*log2(x) = log(x)/log(2)*/ + agcattack = 27 + log(bitrate / (10 * FXTAL)) / log(2); + } else { + agcattack = 27 + log(bitrate / FXTAL) / log(2); + } + write_register(AGCATTACK, agcattack); +} + +/*This function configures registers AGCDECAY*/ +void Comms::configure_AGCDECAY(int bitrate, uint8_t modValue ) +{ + uint8_t agcdecay; + if(modValue == 0) { + agcdecay = 27 + log(bitrate / (100 * FXTAL)) / log(2); + } else { + agcdecay = 27 + log(bitrate / (10 * FXTAL)) / log(2); + } + write_register(AGCDECAY, agcdecay); +} + +/*This function configures registers PHASEGAIN*/ +void Comms::configure_PHASEGAIN(uint8_t modValue) +{ + if(modValue == 0) { + write_register(PHASEGAIN, 0x00); + } else { + write_register(PHASEGAIN, 0x03); + } +} + +/*This function configures registers FREQGAIN*/ +void Comms::configure_FREQGAIN(uint8_t modValue) +{ + if(modValue < 7) { + write_register(FREQGAIN, 0x06); + } else { + write_register(FREQGAIN, 0x03); + } +} + +/*This function configures registers FREQGAIN2*/ +void Comms::configure_FREQGAIN2() +{ + write_register(FREQGAIN2, 0x06); +} + +/*This function configures registers AMPLGAIN*/ +void Comms::configure_AMPLGAIN() +{ + write_register(AMPLGAIN, 0x06); +} + +/*--------------------------------------------------------------*/ + +/*This function translates the String modulation into the value to be assigned +*to the register in hexadecimal*/ +uint8_t Comms::getModulationReg(int modulation) +{ + uint8_t modValue; + switch (modulation){ + case ASK: + modValue = 0x00; + break; + case PSK: + modValue = 0x04; + break; + case OQPSK: + modValue = 0x06; + break; + case MSK: + modValue = 0x07; + break; + case FSK: + modValue = 0x0B; + break; + case GFSK: + modValue = 0x0F; + break; + } + return modValue; +} diff --git a/src/Arduino/comms_test/comms.h b/src/Arduino/comms_test/comms.h new file mode 100644 index 0000000..e01c589 --- /dev/null +++ b/src/Arduino/comms_test/comms.h @@ -0,0 +1,136 @@ +/* AX5042 library for Arduino */ + +#ifndef _COMMS_H +#define _COMMS_H + +#include "Arduino.h" +#include /* For communication via SPI. */ +#include "hdlc.h" + +class Comms; +class Comms +{ + public: + Comms();/*Constructor not used*/ + ~Comms();/*Destructor not used*/ + void configure(); + void tx(uint8_t *data, int data_size); + char *rx(); + void change_x(int parameter, int value); + unsigned int read_register(byte this_register); + void write_register(byte this_register, byte this_value); + private: + void auto_ranging(); + void configure_PLLLOOP(int band); + void configure_FREQ(int fcarrier); + void configure_TXPWR(); + void configure_IFFREQ(); + void configure_FSKDEV(int bitrate); + void configure_TXRATE(int bitrate); + uint32_t configure_CICDEC(int bitrate); + void configure_MODULATION(int modulation); + uint32_t compute_FSKMUL(int bitrate, uint8_t tmgcorrfrac, uint8_t modValue, uint32_t cicdec); + uint32_t configure_DATARATE(int bitrate, int cicdec, int fskmul); + void configure_TMGGAIN(uint32_t fskmul, uint32_t datarate, int tmgcorrfrac); + void configure_AGCATTACK(int bitrate, uint8_t modValue); + void configure_AGCDECAY(int bitrate, uint8_t modValue); + void configure_PHASEGAIN(uint8_t modValue); + void configure_FREQGAIN(uint8_t modValue); + void configure_FREQGAIN2(); + void configure_AMPLGAIN(); + uint8_t getModulationReg(int modulation); +}; + +/* REGISTERS DECLARATION */ + +#define REVISION 0x00 +#define SCRATCH 0x01 +#define PWRMODE 0x02 +#define XTALOSC 0x03 +#define FIFOCTRL 0x04 +#define FIFODATA 0x05 +#define IRQMASK 0x06 +#define IRQREQUEST 0x07 +#define IFMODE 0x08 +#define PINCFG1 0x0C +#define PINCFG2 0x0D +#define PINCFG3 0x0E +#define IRQINVERSION 0x0F +#define MODULATION 0x10 +#define ENCODING 0x11 +#define FRAMING 0x12 +#define CRCINIT3 0x14 +#define CRCINIT2 0x15 +#define CRCINIT1 0x16 +#define CRCINIT0 0x17 +#define FREQ3 0x20 +#define FREQ2 0x21 +#define FREQ1 0x22 +#define FREQ0 0x23 +#define FSKDEV2 0x25 +#define FSKDEV1 0x26 +#define FSKDEV0 0x27 +#define IFFREQHI 0x28 +#define IFFREQLO 0x29 +#define PLLLOOP 0x2C +#define PLLRANGING 0x2D +#define TXPWR 0x30 +#define TXRATEHI 0x31 +#define TXRATEMID 0x32 +#define TXRATELO 0x33 +#define MODMISC 0x34 +#define AGCTARGET 0x39 +#define AGCATTACK 0x3A +#define AGCDECAY 0x3B +#define AGCCOUNTER 0x3C +#define CICSHIFT 0x3E +#define CICDECHI 0x3E +#define CICDECLO 0x3F +#define DATARATEHI 0x40 +#define DATARATELO 0x41 +#define TMGGAINHI 0x42 +#define TMGGAINLO 0x43 +#define PHASEGAIN 0x44 +#define FREQGAIN 0x45 +#define FREQGAIN2 0x46 +#define AMPLGAIN 0x47 +#define TRKAMPLHI 0x48 +#define TRKAMPLLO 0x49 +#define TRKPHASEHI 0x4A +#define TRKPHASELO 0x4B +#define TRKFREQHI 0x4C +#define TRKFREQLO 0x4D +#define APEOVER 0x70 +#define PLLVCOI 0x72 +#define PLLRNG 0x74 +#define REF 0x7C +#define RXMISC 0x7D + +/*Parameters declaration*/ + +#define BITRATE_DEFAULT 100000 +#define FCARRIER 433000000 +#define FIF 1000000 +#define FXTAL 16300000 +#define H 0.5 +#define TMGCORRFRAC_DEFAULT 32 +#define MOD_DEFAULT 4 +#define BANDSEL 1 + +typedef enum { + FREQUENCY, + BITRATE, + MODULATION_TYPE, + TMRECOV +} VariablesChangeX; + +typedef enum { + ASK, + PSK, + OQPSK, + MSK, + FSK, + GFSK +} ModulationTypes; + +#endif diff --git a/src/Arduino/comms_test/comms_test.ino b/src/Arduino/comms_test/comms_test.ino index 4703549..b86bfcd 100644 --- a/src/Arduino/comms_test/comms_test.ino +++ b/src/Arduino/comms_test/comms_test.ino @@ -7,8 +7,8 @@ #include #include #include "comms_test.h" -#include -#include +#include "hdlc.h" +#include "comms.h" Comms comms; diff --git a/src/Arduino/comms_test/hdlc.cpp b/src/Arduino/comms_test/hdlc.cpp new file mode 100644 index 0000000..feceb67 --- /dev/null +++ b/src/Arduino/comms_test/hdlc.cpp @@ -0,0 +1,120 @@ +/* + * RECEPTION RUTINE + * Following HDLC Receive Flow Chart from AXSEM AX5042 Programming Manual (page 32) + */ +#include "hdlc.h" + +Comms coms; + +char *hdlc_rx() +{ + char *response; + char data_size; + int received; + int i = 2; + unsigned int control; + unsigned int data; + control = coms.read_register(FIFOCTRL); + data = coms.read_register(FIFODATA); + while(control & (bit(1) | bit(0)) != 0x01) { // Search for delimiter + control = coms.read_register(FIFOCTRL); + data = coms.read_register(FIFODATA); + } + received = 0; + while(received == 0) { + control = coms.read_register(FIFOCTRL); + data = coms.read_register(FIFODATA); + if(control & bit(0) == bit(0)) { + *response = 2; + received = 1; + /*DISCARDED PACKAGE: Abort detected*/ + } else if(control & bit(1) == bit(1)) { + if(data & bit(3) == bit(3)) { + if(data & (bit(2) | bit(1) | bit(0)) == 0x06) { + received = 1; + data_size = i - 2;/*The last two frames are of CRC, we must delete them.*/ + *response = 0; + *(response + 1) = data_size; + /*CRC OK: end of packet*/ + } else { + received = 0; + i = 2; /*We reset the counter to 2, pointing at the first data position*/ + /*DISCARDED PACKAGE: Number of packet bits not divisible by 8*/ + } + } else { + received = 1; + *response = 1; + /*DISCARDED PACKAGE: wrong CRC + *We will notify the HWDmods of this reception */ + } + } else { + received = 0; + *(response + i) = data; + i++; + /*DATA FRAME: save it to data buffer*/ + } + } + return response; +} + + +/* + * TRANSMITION RUTINE + * Following HDLC transmit Flow Chart from AXSEM AX5042 Programming Manual (page 31) + */ + +void send_preamble() +{ + int i = 0; + unsigned int control = 0x03; + unsigned int data = 0xAA; + while(i < 10) { + coms.write_register(FIFOCTRL, control); + coms.write_register(FIFODATA, data); + i++; + } +} + +void send_packet(uint8_t * data, int data_size) +{ + int i = 0; + + /*HDLC FLAG, PACKET DELIMITER*/ + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0x7E); + + for(i = 0; i < data_size; i++) { + coms.write_register(FIFOCTRL, 0x00); + coms.write_register(FIFODATA, data[i]); + } + + /*CRC*/ + coms.write_register(FIFOCTRL, 0x01); + coms.write_register(FIFODATA, 0x00); + coms.write_register(FIFOCTRL, 0x01); + coms.write_register(FIFODATA, 0x00); + + /*HDLC FLAG, PACKET DELIMITER*/ + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0x7E); + +} + +void send_ABORT() +{ + //HDLC ABORT + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0xFF); + coms.write_register(FIFOCTRL, 0x03); + coms.write_register(FIFODATA, 0xFF); +} + +void hdlc_tx(uint8_t *data, int data_size) +{ + send_preamble(); + + send_packet(data,data_size); + + send_ABORT(); +} + diff --git a/src/Arduino/comms_test/hdlc.h b/src/Arduino/comms_test/hdlc.h new file mode 100644 index 0000000..1d4ee85 --- /dev/null +++ b/src/Arduino/comms_test/hdlc.h @@ -0,0 +1,15 @@ + +#ifndef _HDLC_H +#define _HDLC_H + +#include "Arduino.h" +#include /* For communication via SPI. */ +#include "comms.h" + +char *hdlc_rx(); +void send_preamble(); +void send_packet(char *data, int data_size); +void send_ABORT(); +void hdlc_tx(uint8_t *data, int data_size); + +#endif \ No newline at end of file