12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718 |
- //2023.20.03 win port
- //2023.10.06 +due_download_prog() file output, !!! +static int min_ticks
- //2023.10.07 +int due_download_prog_save_to_file(int fd,due_prog_t *program);
- //10.18 +int due_download_prog_save_to_file_command/data
- /*
- Copyright 2018, Carl Michal
- This file is part of due-pp-lib.
- due-pp-lib is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or (at
- your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /*
- pulse program assembler for Due pulse programmer.
- port C pins available C1-9, C12-19, 21-26 and 28-30 =9+8+6+3 = 26 pins
- could use A: 0-4 6-7 8-9 (RX0, TX0), 10-29 ? = 5+2+20 = 29 if give up RX/TX
- A.21 and C.30 are likely hard to use - hooked to LEDs, no headers.
- (8/9 = Uart, could maybe use, 21 maybe used for usb led?
- portB 12-21, 25-27, port D0-10
- A.29 and C.26 are same pin
- A.28 and C.29 are same pin
- stick with port C for now.
- so - we have 25 C pins, 28 A pins but 2 that are shared so 26/27 or 25/28 or 24/29
- C1-9, 12-19, 21-26 and 28-30. These are:
- C.0 = A.0 = D69 CANTX0
- C.1 = D33 A.1 = D68 CANRX0
- C.2 = D34 A.2 = A7 = D61
- C.3 = D35 A.3 = A6 = D60
- C.4 = D36 A.4 = A5 = D59
- C.5 = D37 A.5 =
- C.6 = D38 A.6 = A4 = D58
- C.7 = D39 A.7 = D31
- C.8 = D40 A.8 = D0 (RX0 no go?)
- C.9 = D41 A.9 = D1 (TX0 no go?)
- C.10 = A.10 = D19
- C.11 = A.11 = D18
- C.12 = D51 A.12 = D17
- C.13 = D50 A.13 = D16
- C.14 = D49 A.14 = D23
- C.15 = D48 A.15 = D24
- C.16 = D47 A.16 = A0 = D54
- C.17 = D46 A.17 = D70
- C.18 = D45 A.18 = D71
- C.19 = D44 A.19 = D42
- C.20 = A.20 = D43
- C.21 = D9 A.21 = D73 (not easy)
- C.22 = D8 A.22 = A3 = D57
- C.23 = D7 A.23 = A2 = D56
- C.24 = D6 A.24 = A1 = D55
- C.25 = D5 A.25 = D74 (MISO)
- C.26 = D4/D87 A.26 = D75 (MOSI)
- C.27 = A.27 = D76 (SCK)
- C.28 = D3 A.28 = D77/D10
- C.29 = D10/D77 A.29 = D87/D4
- C.30 = D72 (not easy)
- C.31 =
- */
- #include "due-pp-lib.h"
- #include <math.h>
- #include <unistd.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/file.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fstream>
- #include "serialib.h" // Serial library
- //#include "serialib.h" // Serial library
- //#include <fcntl.h>
- //#include "fcntl.h"
- #include <unistd.h>
- //#include <termios.h>
- //#include "termios.h"
- #include <sys/time.h>
- //#include "file.h"
- //#include "flock.c"
- //sleep
- #include <thread>
- #include <chrono>
- #define BUFFLEN 80
- #define NUM_OPCODES 14
- #define START_LOOP 0
- #define END_LOOP 1
- #define BRANCH 2
- #define EXIT 3
- #define SUB_START 4
- #define SUB_END 5
- #define EXT_TRIG 6
- #define TRIG_MAX 7
- #define WRITE_DACS 8
- #define WRITE_ALT 9
- #define SWAP_TO_ALT 10
- #define SWAP_TO_DEFAULT 11
- #define SWAP_TO_DACS 12
- #define WRITE_DEFAULT 13
- #define CALL_SUB 255
- /* Operations for the `flock' call. */
- #define LOCK_SH 1 /* Shared lock. */
- #define LOCK_EX 2 /* Exclusive lock. */
- #define LOCK_UN 8 /* Unlock. */
- /* Can be OR'd in to one of the above. */
- #define LOCK_NB 4 /* Don't block when locking. */
- //
- #define O_NOCTTY 0
- #define STATE_INITIALIZED 1
- #define STATE_FINALIZED 2
- #define STATE_EXITED 3
- // This is the maximum length of an unrolled loop in the flash program:
- #define MAX_QUE_LEN 12000
- // branch and exit assigned to 15?
- // this isn't a great system since the minimums don't necessarily line up
- // with opcodes. Here the NUM_OPCODES element is for an ordinary event,
- // and NUM_OPCODES+1 is for CALL_SUB. EXT_TRIG and TRIG_MAX
- // have restrictions on both the event themselves and the preceding.
- // Some of these are for the events preceding. Take the bigger of the two and
- // use for both.
- //int min_ticks[NUM_OPCODES+2] = {20,20,20,25,0,25,20,25,25,25,25,25,25,20,10,25};
- static int min_ticks[NUM_OPCODES+2] = {20,20,20,25,0,25,20,25,25,25,25,25,25,20,10,25}; //! no static - ld error
- void checksum_data(unsigned char *c1, unsigned char *c2, int len, unsigned int *data) {
- // calculate checksums for the data. Based on what Bruker does in SBS.
- unsigned int i, ch1 = 0, ch2 = 0;
- // unsigned char *cdata;
- /* d0 d1 d2 d3 d4 d5 ... dn
- 1 2 3 4 5 6 ... n
- n+1 n n-1 n-2 ... 2
- for the first checksum, multiply top row elements by middle row elements. Sum, and keep low 8 bits.
- For the second, use the lower row.
- */
- // cdata = (unsigned char *) data;
- /* for (i = 0; i < len*4; i++) {
- ch1 += (i+1)*cdata[i];
- ch2 += (len*4+1-i)*cdata[i];
- } */
- for (i = 0; i < len; i++) {
- ch1 += (i+1)*data[i];
- ch2 += (len+1-i)*data[i];
- }
- *c1 = ch1 & 0xff;
- *c2 = ch2 & 0xff;
- }
- unsigned int due_shift_bits(unsigned int inputs, unsigned int port){
- // look at active port, shift accordingly
- unsigned int outputs=0;
- switch (port){
- case DEFAULT_PORT:
- //this assumes port C, missing bits 0, 10, 11, 20, 27, 30, 31
- // 25 useful bits.
- /*
- 0-8 -> 1-9
- 9-16 -> 12-19
- 17-22 -> 21-26
- 23-24 -> 28-29
- */
- //31-28 27-24 23-20 19-16 15-12 11-8 7-4 3-0
- outputs |= ((inputs & 0x01800000) << 5);
- outputs |= ((inputs & 0x007e0000) << 4);
- outputs |= ((inputs & 0x0001fe00) << 3);
- outputs |= ((inputs & 0x000001ff) << 1);
- // printf("shifting bits for default port was: 0x%x, now: 0x%x\n",inputs,outputs);
- return outputs;
- break;
- case ALT_PORT:
- // this assumes port A, missing bits: 5, 8, 9, 21, 28-31.
- //24 useful bits.
- /*
- 0-4 -> 0-4
- 5-6 -> 6-7
- 7-17 -> 10-20
- 18-23 -> 22-27
- */
- outputs |= ((inputs & 0x00fc0000) << 4 );
- outputs |= ((inputs & 0x0003ff80) << 3 );
- outputs |= ((inputs & 0x00000070) << 1 );
- outputs |= ((inputs & 0x0000000f));
- // printf("shifting bits for alt port was: 0x%x, now: 0x%x\n",inputs,outputs);
- return outputs;
- break;
- case DAC_PORT:
- // do nothing
- return inputs;
- break;
- default:
- printf("duepp: in shift bits with unknown port to shift for, doing nothing!\n");
- printf("This can happen if you have a subroutine that is never called\n");
- return inputs;
- }
- // return inputs;
- }
- int do_play_queue(due_prog_t *program, uint32_t whats_next){
- /* this fills in the jump address for the events that have been queued, these events end
- with a function determined by whats_next: either a loop start, a loop end, a bare branch, or
- a branch to exit. */
- // need to deal with CALL_SUB and SUB_END.
- if (program->queued_events > 12000 ){
- printf("duepp program->queued_events out of range: %i\n",program->queued_events);
- program->error = 1;
- return -1;
- }
- if (program->queued_events > 12000){
- printf("duepp got program->queued_events = %i, is > 12000, can't handle\n",program->queued_events);
- program->error = 1;
- return -1;
- }
- if (program->queued_events == 0){
- if (program->dpos > MAXDATA-2){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- program->data[program->dpos] = (whats_next << 16);
- program->dpos += 1;
- // should only ever get: START_LOOP, EXIT, SUB_END, SWAP_TO_ALT, SWAP_TO_DEFAULT, CALL_SUB, SWAP_TO_DACS
- }
- else if (program->queued_events > 0){ // these have direct endings, optimized for speed.
- if (whats_next <= BRANCH){
- program->data[program->queue_pos] = (whats_next << 16 ) | program->queued_events;
- program->queued_events = 0;
- }
- else if (whats_next < NUM_OPCODES){ // all these do a branch to get to the operation.
- if (program->dpos > MAXDATA-2){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- program->data[program->queue_pos] = (BRANCH << 16 ) | program->queued_events;
- program->queued_events = 0;
- program->data[program->dpos] = (whats_next << 16 ) ;
- program->dpos += 1;
- }
- else if (whats_next == CALL_SUB){// this one's special
- program->data[program->queue_pos] = (BRANCH <<16) | program->queued_events;
- // call_sub gets three more instructions inserted
- // printf("queue for call_sub, queued events: %i\n",program->queued_events);
- program->queued_events = 0;
- }
- else{
- printf("duepp: play_queue got unknown what's next\n");
- program->error = 1;
- return -1;
- }
- }
- return 0;
- }
- int play_queue(due_prog_t *program, int whats_next){
- int rval = 0;
- int i,dposi,j,cache_queued_events;
- if (program->queued_events <= MAX_QUE_LEN){
- return do_play_queue(program, whats_next);
- }
- // ok, so we have more than the max number of events,
- // (it can never be more than double though) Look for an event that's long enough
- // to break the queue up.
- if (program->dpos > MAXDATA-2){
- printf("duepp: not enough room left to split events\n");
- program->error = 1;
- return -1;
- }
- for (i=MAX_QUE_LEN-1;i >= program->queued_events-MAX_QUE_LEN-1;i--){
- // program->dpos points at the next event, each event has two entries - an output word and a timer delay
- dposi = program->dpos-2*program->queued_events+2*i; // points to the output word of the i'th event in the queue.
- if ( program->data[dposi+1] >= min_ticks[BRANCH] ) // use a 20 tick minimum for breaking up.
- break;
- }
- // i is the index of the last event in the first queue.
- if ( i >= program->queued_events-MAX_QUE_LEN-1 ){
- i+=1; // now i is the first event in the second queue.
- // slide all events from i to the end down a slot
- for (j = program->queued_events; j>=i ; j--){
- dposi = program->dpos-2*program->queued_events+2*j;
- program->data[dposi+2]=program->data[dposi+1];
- program->data[dposi+1]=program->data[dposi];
- // that leaves a slot just before the i'th event to stick in a new jump address
- }
- printf("duepp: breaking %i into two queues of length: %i and %i\n",program->queued_events,i,program->queued_events-i);
- cache_queued_events = program->queued_events;
- program->queued_events = i;
- rval = do_play_queue(program, BRANCH);
- if (rval < 0) return rval;
- // then do the rest
- program->queue_pos = program->dpos-2*cache_queued_events + 2*i;
- program->queued_events = cache_queued_events-i;
- do_play_queue(program, whats_next);
- if (rval < 0) return rval;
- program->dpos += 1; // add one for the new jump address
- }
- else{
- printf("duepp: Got %i events, more than %i, and couldn't find a spot to break it up\n",program->queued_events,MAX_QUE_LEN);
- program->error = 1;
- return -1;
- }
- return 0;
- }
- int due_add_event(due_prog_t *program, unsigned int outputs, unsigned int ticks) {
- // printf("due_add_event with outputs: 0x%x, ticks: %i\n",outputs,ticks);
- if (ticks < min_ticks[NUM_OPCODES]){
- printf("duepp: Got due_add_event with %i ticks. Must be at least: %i\n",ticks,min_ticks[NUM_OPCODES]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to add an event, the program must be in STATE_INITIALIZED or defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (program->queued_events == 0){
- if (program->dpos > MAXDATA-2){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- program->queue_pos = program->dpos;
- program->dpos += 1;
- }
- program->queued_events += 1;
- program->events += 1;
- if (program->dpos > MAXDATA-3){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- if (program->auto_shift) outputs = due_shift_bits(outputs,program->active_port);
- program->data[program->dpos] = outputs;
- program->dpos += 1;
- program->data[program->dpos] = ticks;
- program->dpos += 1;
- program->last_ticks = ticks;
- // printf("due add_event, putting outputs 0x%x in event: %i\n",outputs,program->dpos);
- // printf("due add_event, putting outputs 0x%x in event: %i\n",outputs,program->dpos);
- return 0;
- } //due_add_event
- int due_start_loop(due_prog_t *program, unsigned int loops,unsigned int outputs, unsigned int ticks) {
- int rval;
- if (program->last_ticks < min_ticks[START_LOOP]){
- printf("duepp: Got start_loop with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[START_LOOP]);
- program->error = 1;
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to start a loop, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- // if there are queued events, do them
- rval = play_queue(program, START_LOOP);
- if (rval < 0 ) return rval;
- if (program->dpos > MAXDATA-2){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- program->data[program->dpos] = loops;
- program->dpos += 1;
- program->loop_level +=1;
- return due_add_event(program, outputs, ticks);
- }
- int due_end_loop(due_prog_t *program, unsigned int outputs, unsigned int ticks) {
- int rval;
- if (ticks < min_ticks[END_LOOP]){
- printf("duepp: Got end_loop with %i ticks. Must be at least: %i\n",ticks,min_ticks[END_LOOP]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to end a loop, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (program->loop_level < 1){
- printf("duepp: Got end_loop, but no loop to end!\n");
- program->error = 1;
- return -1;
- }
- rval = due_add_event(program, outputs, ticks);
- if (rval < 0 ) return rval;
- rval = play_queue(program, END_LOOP);
- program->loop_level -=1;
- return rval;
- }
- int due_init_program(due_prog_t *program,char auto_shift){
- int i;
- program->auto_shift = auto_shift;
- program->active_port = DEFAULT_PORT;
- program->dpos = 0;
- program->events = 0;
- program->queued_events = 0; // how many events to do in the continuous sequence loop.
- program->state = STATE_INITIALIZED;
- program->in_sub = 0;
- program->error = 0;
- for (i=0;i<MAXSUB;i++){
- program->sub_table[i]=0;
- program->sub_entry_port[i] = -1;
- }
- return 0;
- }
- int due_exit_program(due_prog_t *program){
- int rval;
- if (program->last_ticks < min_ticks[EXIT]){
- printf("duepp: Got exit_program with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[EXIT]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED ){
- printf("duepp: got exit_program, but the program must be in STATE_INITIALIZED\n");
- program->error = 1;
- return -1;
- }
- if (program->loop_level != 0){
- printf("duepp: Loop starts and ends don't match, expect trouble!\n");
- program->error = 1;
- return -1;
- }
- rval = play_queue(program, EXIT);
- if (rval < 0 ) return rval;
- program->state = STATE_EXITED;
- return 0;
- }
- int due_swap_to_alt(due_prog_t *program, unsigned int outputs, unsigned int ticks){
- int rval;
- if (program->last_ticks < min_ticks[SWAP_TO_ALT]){
- printf("duepp: Got swap_to_alt with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[SWAP_TO_ALT]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to swap_to_alt, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- rval = play_queue(program, SWAP_TO_ALT);
- if (rval < 0 ) return rval;
- if (program->active_port == ALT_PORT){
- printf("duepp: WARNING: got swap_to_alt when port was already alt?\n");
- }
- program->active_port = ALT_PORT;
- return due_add_event(program, outputs,ticks);
- }
- int due_swap_to_default(due_prog_t *program, unsigned int outputs, unsigned int ticks){
- int rval;
- if (program->last_ticks < min_ticks[SWAP_TO_DEFAULT]){
- printf("duepp: Got swap_to_default with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[SWAP_TO_DEFAULT]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to swap_to_default, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- rval = play_queue(program, SWAP_TO_DEFAULT);
- if (rval < 0 ) return rval;
- if (program->active_port == DEFAULT_PORT){
- printf("duepp: WARNING: got swap_to_default when port was already default?\n");
- }
- program->active_port = DEFAULT_PORT;
- return due_add_event(program, outputs,ticks);
- }
- int due_swap_to_dacs(due_prog_t *program, unsigned int dac0, unsigned int dac1, unsigned int ticks){
- int dacword,rval;
- if (program->last_ticks < min_ticks[SWAP_TO_DACS]){
- printf("duepp: Got swap_to_dacs with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[SWAP_TO_DACS]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to swap_to_dacs, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- dacword = dac0 | dac1<<16 | 1<<28;
- rval = play_queue(program, SWAP_TO_DACS);
- if (rval < 0 ) return rval;
- if (program->active_port == DAC_PORT){
- printf("duepp: WARNING: got swap_to_dacs when port was already dacs?\n");
- }
- program->active_port = DAC_PORT;
- return due_add_event(program, dacword,ticks);
- }
- // There are a few things that need to get filled in.
- // In the subroutines themselves, the first word will contain a typical branch to be resolved.
- // that needs to get resolved, then copied in to the callers branch spot
- // the SUB_END instructions also need to get resolved
- // Finally, we need to calculate the data offsets and give them to the caller.
- // the sub_table contains the information needed to do the data offsets.
- int due_finalize_program(due_prog_t *program){
- int inst,elements,i;
- // in here we resolve subroutines.
- if (program->state != STATE_EXITED || program->in_sub == 1){
- printf("duepp: to finalize program, the program must be in STATE_EXITED, and must not be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (program->loop_level != 0){
- printf("duepp: Loop starts and ends don't match!\n");
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_EXITED){
- printf("duepp: got finalize_program, but haven't yet exited\n");
- program->error = 1;
- return -1;
- }
- if (program->in_sub){
- printf("duepp: got finalize_program, but still inside a subroutine!\n");
- program->error = 1;
- return -1;
- }
- // now in here, we need to go through and get the subroutine calls
- // ready. We find each subroutine call, copy the number of event and
- // the what's next code in from the subroutine header (which we can
- // locate in the sub_table) we can also calculate the data offset
- inst = 0 ;
- i=0;
- while( i < program->dpos){
- inst = program->data[i]>>16;
- elements = program->data[i] & 0xffff;
- // printf("got inst: %i, with elements: %i at pos: %i\n",inst,elements,i);
- if (inst == CALL_SUB ){ // elements is the subroutine_id - which we only need to look up the data address.
- // leave program->data[i] alone. run-time resolver will take care of it.
- // 2. calculate the address for the jump -into the generic branch
- // printf("got sub call at pos %i ",i);
- if (program->sub_table[elements] == 0){
- printf("duepp: trying to resolve a subroutine, id: %i, but subroutine not found.\n",elements);
- program->error = 1;
- return -1;
- }
- program->data[i+1] = ((program->sub_table[elements]+1) - (i+3))*4; // data offset - point it one past the jump header
- program->data[i+2] = program->data[program->sub_table[elements]]; // copy the jump header from the start of the subroutine.
- // printf(" data offset is %i, target is: %i, current is: %i\n",program->data[i+1],program->sub_table[elements]+1,(i+3));
- i+=3;
- }
- else{
- i += 1; // advance past the address
- i += 2*elements; // advance past the events
- // if (inst == START_LOOP || inst == EXIT || inst == WRITE_DACS || inst == WRITE_ALT || inst == WRITE_DEFAULT ) i += 1; // for start loop, advance past the loop count.
- if (inst == START_LOOP || inst == WRITE_DACS || inst == WRITE_ALT || inst == WRITE_DEFAULT ) i += 1; // for start loop, advance past the loop count.
- }
- }
- program->state = STATE_FINALIZED;
- return 0;
- }
- // during pulse prog creation, the caller's three words are:
- // CALL_SUB<<16 | subroutine_id
- // blank
- // blank
- // after finalize_program, these are replaced with:
- // CALL_SUB <<16
- // data offset
- // what's_next << 16 | events [ for subroutine_id] - copied
- // run time resolver replaces them with:
- // address for start_sub code
- // data_offset (leaves alone)
- // resolves this as any other event.
- int due_call_sub(due_prog_t *program,unsigned int subroutine_id, unsigned int outputs,unsigned int ticks){
- int rval;
- if (ticks < min_ticks[NUM_OPCODES+1]){
- printf("duepp: Got call_sub with %i ticks. Must be at least: %i\n",ticks,min_ticks[NUM_OPCODES+1]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to call a subroutine, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (subroutine_id >= MAXSUB){
- printf("duepp: subroutine id of %i is too big, max is: %i\n",subroutine_id,MAXSUB-1);
- return -1;
- }
- if (program->sub_entry_port[subroutine_id] == -1){
- program->sub_entry_port[subroutine_id] = program->active_port;
- }
- else if (program->sub_entry_port[subroutine_id] != program->active_port){
- printf("duepp: WARNING: Got call to subroutine %i with active port %i. Previous call had active port: %i\n",subroutine_id,
- program->active_port,program->sub_entry_port[subroutine_id]);
- }
- rval = due_add_event(program, outputs,ticks);
- if (rval < 0) return rval;
- rval = play_queue(program, CALL_SUB);
- // play_queue will insert
- if (program->dpos > MAXDATA-4){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- program->data[program->dpos] = CALL_SUB <<16 | subroutine_id; //
- // next is the data offset to the start of the subroutine events
- // and after that is the branch address.
- // we don't know enough at this point to fill either of those in.
- program->dpos += 3;
- return rval;
- }
- // start_sub does not create an event! Call this before created the events in the subroutine.
- int due_start_sub(due_prog_t *program, unsigned int subroutine_id){
- if (program->state != STATE_EXITED){
- printf("duepp: in start_sub. Program state needs to be STATE_EXITED\n");
- program->error = 1;
- return -1;
- }
- if (program->in_sub) {
- printf("duepp: subroutine can't be defined inside a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (program->queued_events != 0){
- printf("duepp: got start_sub but had events queued. Shouldn't happen\n");
- program->error = 1;
- return -1;
- }
- if (subroutine_id >= MAXSUB){
- printf("duepp: subroutine id of %i is too big, max is: %i\n",subroutine_id,MAXSUB-1);
- return -1;
- }
- // record where the subroutine data starts. This actually points to the jump
- // address that starts the subroutine data section.
- // This address should never be read from this position, it gets copied into the
- // the data stream at the caller.
- program->sub_table[subroutine_id] = program->dpos;
- // Don't want due_add_event to leave space for a jump address
- // The in_sub flags tells it not to set program->queue_pos.
- program->in_sub = 1;
- program->in_sub_num = subroutine_id;
- program->active_port = program->sub_entry_port[subroutine_id];
- if (program->active_port == -1){
- printf("duepp: WARNING: port for entry of subroutine %i is -1, indicating the subroutine was never called\n",subroutine_id);
- }
- return 0;
- }
- int due_return_from_sub(due_prog_t *program, unsigned int outputs, unsigned int ticks){
- int rval;
- if (program->in_sub != 1){
- printf("duepp: got return from sub, but wasn't in a subroutine!\n");
- program->error = 1;
- return -1;
- }
- if (program->sub_entry_port[program->in_sub_num] != program->active_port){
- printf("duepp: WARNING: Subroutine: %i entered with active port: %i. Leaving with active port: %i\n",program->in_sub_num,
- program->sub_entry_port[program->in_sub_num],program->active_port);
- }
- rval = due_add_event(program, outputs,ticks);
- if (rval < 0) return rval;
- rval = play_queue(program, SUB_END);
- program->in_sub = 0;
- return rval;
- }
- int due_wait_for_trigger(due_prog_t *program,unsigned int outputs,unsigned int ticks){
- int rval;
- // waits for an external trigger. Will wait forever. The requested delay
- // starts when the trigger is received. The requested outputs are set
- // just before we start waiting
- if (program->last_ticks < min_ticks[EXT_TRIG]){
- printf("duepp: Got wait_for_trigger with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[EXT_TRIG]);
- program->error = 1;
- return -1;
- }
- if (ticks < min_ticks[EXT_TRIG]){
- printf("duepp: Got wait_for_trigger with %i ticks. Must be at least: %i\n",ticks,min_ticks[EXT_TRIG]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to wait for trigger, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- rval = due_add_event(program, outputs,ticks);
- if (rval < 0) return rval;
- return play_queue(program, EXT_TRIG);
- }
- int due_wait_for_trigger_max(due_prog_t *program,unsigned int outputs,unsigned int ticks){
- int rval;
- // Waits for an external trigger, but will only wait for a maximum of the
- // requested delay time. There's 1 us delay after the trigger is received.
- // The requested outpus are set just before we start waiting.
- if (program->last_ticks < min_ticks[TRIG_MAX]){
- printf("duepp: Got wait_for_trigger_max with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[TRIG_MAX]);
- program->error = 1;
- return -1;
- }
- if (ticks < min_ticks[TRIG_MAX]){
- printf("duepp: Got wait_for_trigger with %i ticks. Must be at least: %i\n",ticks,min_ticks[TRIG_MAX]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to wait for trigger max, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- rval = due_add_event(program, outputs,ticks);
- if (rval < 0) return rval;
- return play_queue(program, TRIG_MAX);
- }
- int due_write_dacs(due_prog_t *program, unsigned int dac0, unsigned int dac1,unsigned int outputs,unsigned int ticks){
- int rval;
- if (ticks < min_ticks[WRITE_DACS]){
- printf("duepp: Got write_dacs with %i ticks. Must be at least: %i\n",ticks,min_ticks[WRITE_DACS]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to write_dacs, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (program->active_port == DAC_PORT){
- printf("duepp: WARNING: Got write dacs while active port is already dacs!\n");
- }
- rval = due_add_event(program, outputs,ticks);
- if (rval < 0) return rval;
- rval =play_queue(program, WRITE_DACS);
- if (program->dpos > MAXDATA-2){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- program->data[program->dpos] = dac0 | dac1<<16 | 1<<28;
- program->dpos += 1;
- return rval;
- }
- int due_write_alt(due_prog_t *program,unsigned int outputs_alt,unsigned int outputs,unsigned int ticks){
- // first arg is the outputs for port A. Second arg is for whatever was last swapped to.
- // port A outputs will not be synchronized. Should not be latched.
- int rval;
- if (ticks < min_ticks[WRITE_ALT]){
- printf("duepp: Got write_alt with %i ticks. Must be at least: %i\n",ticks,min_ticks[WRITE_ALT]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to write_alt, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (program->active_port == ALT_PORT){
- printf("duepp: WARNING: Got write alt while active port is already alt!\n");
- }
- rval = due_add_event(program, outputs,ticks);
- if (rval < 0) return rval;
- rval = play_queue(program, WRITE_ALT);
- if (program->dpos > MAXDATA-2){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- if (program->auto_shift) outputs_alt = due_shift_bits(outputs_alt,ALT_PORT);
- program->data[program->dpos] = outputs_alt;
- program->dpos += 1;
- return rval;
- }
- int due_write_default(due_prog_t *program, unsigned int outputs_def,unsigned int outputs,unsigned int ticks){
- // first arg is the outputs for port C.
- // port C outputs will be synchronized.
- int rval;
- if (program->last_ticks < min_ticks[WRITE_DEFAULT]){
- printf("duepp: Got write_default with %i ticks in previous event. Must be at least: %i\n",program->last_ticks,min_ticks[WRITE_DEFAULT]);
- program->error = 1;
- return -1;
- }
- if (program->state != STATE_INITIALIZED && program->in_sub == 0){
- printf("duepp: to write_default, the program must be in STATE_INITIALIZED, or must be defining a subroutine\n");
- program->error = 1;
- return -1;
- }
- if (program->active_port == DEFAULT_PORT){
- printf("duepp: WARNING: Got write default while active port is already default!\n");
- }
- rval = play_queue(program, WRITE_DEFAULT); // play out previous events
- if (rval < 0) return rval;
- if (program->dpos > MAXDATA-2){
- printf("duepp: program length overrun\n");
- program->error = 1;
- return -1;
- }
- if (program->auto_shift) outputs_def = due_shift_bits(outputs_def,DEFAULT_PORT);
- program->data[program->dpos] = outputs_def; // stick the new output word in place - it will get latched with the next event.
- program->dpos += 1;
- return due_add_event(program, outputs,ticks);
- }
- //this happens on the arduino:
- // this is the starting address in flash of our unrolled loops:
- #define BASE_ADDR 0x802f8
- #define EVSIZE 12
- void resolve_jumps(due_prog_t *program){
- // program->dpos is how many elements there are in data
- int i,inst=0,elements;
- uint32_t base_addrs[NUM_OPCODES];
- int code_lengths[NUM_OPCODES + 1] = {12000 * EVSIZE, 16 + 12000 * EVSIZE, 20 + 12000 * EVSIZE,
- 4, 2, 10, 8, 50, 58, 10,10,6,6,8,10};
- base_addrs[0] = BASE_ADDR+code_lengths[0];
- for (i=0;i<NUM_OPCODES;i++)
- base_addrs[i] = base_addrs[i-1] + code_lengths[i];
- for (i=0;i<NUM_OPCODES;i++)
- printf("duepp: base addrs: %i 0x%x\n",i,base_addrs[i]);
- i=0;
- while( i < program->dpos){
- inst = program->data[i]>>16;
- elements = program->data[i] & 0xffff;
- printf("duepp: got inst: %i, with elements: %i\n",inst,elements);
- if (inst == CALL_SUB){
- // have to do three things in here:
- // 1. set program->data[i] to the sub start address
- program->data[i] = base_addrs[SUB_START] +1;
- // 2. calculate the address for the jump -into the generic branch
- inst = program->data[i+2] >> 16;
- // i+2 is like a usual one, but don't advance past the elements afterwards.
- elements = program->data[i+2] & 0xffff;
- program->data[i+2] = base_addrs[inst] - EVSIZE*elements +1;
- //3. find the end of the subroutine and stick the SUB_END address in at its end.
- // program->data[i+1] holds the offset, in bytes from the start of the subroutine to the the word following the subroutine call args.
- // advance past the start address, the data offset, and the jump address.
- i+=3;
- }
- else{
- program->data[i] = base_addrs[inst] - EVSIZE* elements + 1; // +1 for bx.
- i += 1; // advance past the address
- i += 2*elements; // advance past the events
- if (inst == START_LOOP || inst == WRITE_DACS || inst == WRITE_ALT ) i += 1; // for start loop or write_DACS, advance past the argument.
- if (inst == WRITE_DEFAULT) i += 2;
- }
- }
- }
- int due_dump_program(due_prog_t *program){
- int i=0, inst, elements,j;
- if (program->state != STATE_FINALIZED ){
- printf("duepp: WARNING. Got dump_program, but program has not been finalized. Subroutine calls are not complete.\n");
- }
- printf("\nProgram Dump\n");
- while( i < program->dpos){
- inst = program->data[i]>>16;
- elements = program->data[i] & 0xffff;
- switch (inst){
- case CALL_SUB:
- printf("%i CALL SUB: to sub id: %i, data offset: %i, sub data starts at: %i,",i,elements,program->data[i+1]/4,i+program->data[i+1]/4+3);
- inst = program->data[i+2]>>16;
- elements = program->data[i+2] & 0xffff;
- printf(" subroutine starts with call at header in position: %i with %i events\n",i+program->data[i+1]/4+2,elements);
- i+=3;
- break;
- case START_LOOP:
- printf("%i START_LOOP header, %i events\n",i,elements);
- for(j=0;j<elements;j++)
- printf("%i outputs: 0x%x time: 0x%x\n",i+2*j+1,program->data[i+1+2*j],program->data[i+1+2*j+1]);
- printf("%i START_LOOP with %i iterations\n",i,program->data[i+1+2*elements]);
- // printf(" start_loop here\n");
- i += 1+2*elements +1; // the header, the elements and the loop counter
- break;
- case END_LOOP:
- printf("%i END_LOOP header, %i events\n",i,elements);
- for(j=0;j<elements;j++)
- printf("%i outputs: 0x%x time: 0x%x\n",i+2*j+1,program->data[i+1+2*j],program->data[i+1+2*j+1]);
- i += 1 +2*elements; // the header, the elements
- printf("%i END_LOOP\n",i);
- // printf(" end_loop here\n");
- break;
- case BRANCH:
- printf("%i BRANCH header, %i events\n",i,elements);
- for(j=0;j<elements;j++)
- printf("%i outputs: 0x%x time: 0x%x\n",i+2*j+1,program->data[i+1+2*j],program->data[i+1+2*j+1]);
- // printf(" branch here\n");
- printf("%i BRANCH\n",i);
- i += 1 +2*elements; // the header, the elements
- break;
- case EXIT:
- printf("%i EXIT\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case SUB_START:
- printf("%i SUB_START\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case SUB_END:
- printf("%i SUB_END\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case EXT_TRIG:
- printf("%i EXT_TRIG\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case TRIG_MAX:
- printf("%i TRIG_MAX\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case WRITE_DACS:
- j = program->data[i+1];
- printf("%i WRITE_DACS with dac vals: %i and %i for dacs %i and %i\n",i,j & 0xfff, (j>>16) & 0xfff, (j >> 12) & 1, (j>>28) & 1 );
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 2;
- break;
- case WRITE_ALT:
- j = program->data[i+1];
- printf("%i WRITE_ALT with value: 0x%x\n",i,j);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 2;
- break;
- case SWAP_TO_ALT:
- printf("%i SWAP_TO_ALT\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case SWAP_TO_DACS:
- printf("%i SWAP_TO_DACS\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case SWAP_TO_DEFAULT:
- printf("%i SWAP_TO_DEFAULT\n",i);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i += 1;
- break;
- case WRITE_DEFAULT:
- printf("%i WRITE_DEFAULT with value: 0x%x - gets latched in with next event.\n",i,program->data[i+1]);
- if (elements > 0) printf("ERROR, got elements > 0: %i\n",elements);
- i+=2;
- break;
- default:
- printf("GOT AN UNKNOWN OPCODE %i and position %i, aborting\n",inst,i);
- i+=1;
- return -1;
- break;
- }
- }
- return 0;
- }
- int my_read(int fd,char *buff,int timeout){
- // reads from serial port till it sees a newline or timeout runs out.
- // timeout measured in 0.1 s intervals
- // buff is assumed to be able to hold 80 characters.
- // returns the number of characters found.
- int i,pos=0,newbytes;
- do{
- i=0;
- do{
- newbytes = read(fd,&buff[pos],1);
- if (newbytes == -1){ //probably woken by signal
- return -1;
- }
- if (newbytes == 1){
- if (buff[pos] == '\n') {
- buff[pos+1] = 0;
- return pos+1;
- }
- pos += 1;
- i=0;
- }
- else
- i += 1;
- }while ((i<timeout || timeout == 0) && newbytes == 0);
- }while ((i < timeout || timeout == 0) && pos < BUFFLEN-1);
- buff[pos] = 0;
- return pos;
- }
- int my_read0(int fd,char *buff,int timeout){
- // reads from serial port till it sees a newline or timeout runs out.
- // timeout measured in 0.1 s intervals
- // buff is assumed to be able to hold 80 characters.
- // returns the number of characters found.
- int i,pos=0,newbytes;
- for (i=0;i<timeout;i++){
- newbytes=read(fd,&buff[pos],BUFFLEN-pos-1);
- pos += newbytes;
- buff[pos] = 0;
- if (timeout == 0) i = 0; // wait forever.
- if (pos > BUFFLEN-2 ) return pos;
- if (strstr(buff,"\n") != NULL)
- break;
- }
- // printf("my_read, returning: %s, length: %i",buff,pos);
- return pos;
- }
- void due_close_prog(int fd){
- if (fd >=0){
- //flock(fd,LOCK_UN);
- //close(fd);
- }
- }
- int due_open_prog(char *device){
- //struct termios myterm;
- int fd0,bytes_read,rval;
- char sbuff[BUFFLEN];
- // fd0 = open(device, O_RDWR | O_NOCTTY);
- if (fd0 < 0){
- printf("duepp: can't open port to programmer %s\n",device);
- return -1;
- }
- //rval = flock(fd0,LOCK_EX|LOCK_NB); // exclusive lock, don't block if we can't.
- if (rval < 0){
- printf("duepp: Couldn't obtain lock on due programmer board\n");
- close(fd0);
- return -1;
- }
- //tcgetattr(fd0,&myterm);
- //myterm.c_iflag = 0;
- //myterm.c_oflag= CR0; //Carriage return delay mask. Values are CR0, CR1, CR2, or CR3.
- //myterm.c_cflag = CS8 |CLOCAL|CREAD|B38400; // speed doesn't matter for usb
- //myterm.c_lflag=0;
- //myterm.c_cc[VMIN]=0; // non-blocking
- //myterm.c_cc[VTIME]=1; // returns after 0.1s if no characters available
- //tcsetattr(fd0,TCSANOW, &myterm);
- // tcflush(fd0,TCIFLUSH);
- printf("duepp: writing Q: ");
- //write(fd0,"Q",1);
- // bytes_read = my_read(fd0,sbuff,25);
- if (bytes_read > 0 ){
- printf("duepp: Got: %s",sbuff);
- if (strncmp(sbuff,"Due pulse programmer v1",23) == 0)
- return fd0;
- }
- //rval=flock(fd0,LOCK_UN);
- //close(fd0);
- return -1;
- }
- int due_download_prog(int fd,due_prog_t *program){
- char cbyte[3];
- char sbuff[BUFFLEN];
- unsigned char c1,c2;
- int c1d,c2d;
- int i,bytes_read;
- struct timeval start_time,end_time;
- struct timezone tz;
- double d_time;
- if (fd <= 0){
- printf("duepp: due_download: got invalid file descriptor\n");
- return -1;
- }
- if (program->error != 0){
- printf("duepp: pulse program has an error flag set, will not download!\n");
- return -1;
- }
- if (program->state != STATE_FINALIZED){
- printf("duepp: WARNING. Program has not been finalized. If it contains any subroutines, bad things will happen.\n");
- }
- gettimeofday(&start_time,&tz);
- printf("duepp: Sending prog size: %i ",program->dpos);
- fflush(stdout);
- // write(fd,"D",1);
- // send data length, low byte, high byte
- cbyte[0] = 'D';
- cbyte[1] = program->dpos & 0xff;
- cbyte[2] = (program->dpos>>8)&0xff;
- write(fd,cbyte,3);
- bytes_read = my_read(fd,sbuff,5000);
- if (bytes_read > 0 ){
- printf("duepp: Got: %s",sbuff);
- if (strstr(sbuff,"size ok") == NULL){
- printf("duepp: didn't get size ok, aborting\n");
- return -1;
- }
- }
- else{
- printf("duepp: no response to program size\n");
- return -1;
- }
- // then data.
- printf("duepp: Sending program: \n");
- fflush(stdout);
- // first do 512 byte blocks: = 128 4-byte words
- for ( i = 0 ; i+128 < program->dpos ; i += 128){
- // printf("512 byte block at pos: %i ",i);
- write(fd,&(program->data[i]),512);
- bytes_read = my_read(fd,sbuff,100);
- //printf("got: %s",sbuff);
- }
- //write the rest:
- // printf("writing final %i words\n",(program->dpos-i));
- write(fd,&(program->data[i]),(program->dpos-i)*4);
- //write(fd,&data[i],dpos*4);
- bytes_read = my_read(fd,sbuff,10000);
- if (bytes_read > 0){
- printf("duepp: got: %s",sbuff);
- if (strstr(sbuff,"data received") != NULL){ // first two bytes are checksums
- gettimeofday(&end_time,&tz);
- d_time=(end_time.tv_sec-start_time.tv_sec)*1e6
- +(end_time.tv_usec-start_time.tv_usec);
- // fprintf(stderr,"downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- printf("duepp: downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- // check checksums
- checksum_data(&c1,&c2,program->dpos,program->data);
- sscanf(sbuff,"%i %i",&c1d,&c2d);
- if (c1 != c1d || c2 != c2d) {
- printf("duepp: checksums don't match! I calculate: %i %i, received: %i %i\n",c1&0xff,c2&0xff,c1d,c2d);
- return -1;
- }
- // else printf("checksum match: %i %i, %i %i\n",c1&0xff, c2&0xff,c1d,c2d);
- return 0;
- }
- }
- printf("duepp: no response to sent program\n");
- return -1;
- } //due_download_prog
- int due_upload_trajectory(serialib &serial, due_prog_t *program){
- // serialib serial; // Serial object
- // std::ostream OutStream();
- // OutStream <<"message";
- #ifdef LogToFile
- std::ofstream logostream;
- logostream.open("log.txt");
- #else //log to std::cout
- std::ostream& logostream = std::cout;
- #endif
- char buffer[255];
- char cbyte[3];
- char sbuff[BUFFLEN];
- unsigned char c1,c2;
- int c1d,c2d;
- int i,bytes_read;
- struct timeval start_time,end_time;
- struct timezone tz;
- double d_time;
- // if (fd <= 0){
- // printf("duepp: due_download: got invalid file descriptor\n");
- // return -1;
- // }
- printf("---- due_upload_trajectory ------\n");
- if (program->error != 0){
- printf("duepp: pulse program has an error flag set, will not download!\n");
- return -1;
- }
- if (program->state != STATE_FINALIZED){
- printf("duepp: WARNING. Program has not been finalized. If it contains any subroutines, bad things will happen.\n");
- }
- gettimeofday(&start_time,&tz);
- printf("duepp: Sending prog size: %i ",program->dpos);
- fflush(stdout);
- // write(fd,"D",1);
- // send data length, low byte, high byte
- cbyte[0] = 'D';
- cbyte[1] = program->dpos & 0xff;
- cbyte[2] = (program->dpos>>8)&0xff;
- serial.writeBytes(cbyte,3);
- // bytes_read = my_read(fd,sbuff,5000);
- // if (bytes_read > 0 ){
- // printf("duepp: Got: %s",sbuff);
- // if (strstr(sbuff,"size ok") == NULL){
- // printf("duepp: didn't get size ok, aborting\n");
- // return -1;
- // }
- // }
- // else{
- // printf("duepp: no response to program size\n");
- // return -1;
- // }
- // // then data.
- sleep(1);
- int ii = serial.available();
- logostream << "D serial.available = " << ii<< std::endl;
- serial.readString(buffer, '\n', 254, 1000);
- logostream << "D serial.readString = " << buffer << std::endl;
- printf("duepp: Sending program: \n");
- fflush(stdout);
- std::cout<<"program->dpos: " << std::dec << program->dpos <<std::endl;
- i = 0;
- // first do 512 byte blocks: = 128 4-byte words
- for ( i = 0 ; i+128 < program->dpos ; i += 128)
- {
- printf("---- loop ------\n");
- // printf("512 byte block at pos: %i ",i);
- serial.writeBytes(&(program->data[i]),512);
- sleep(1);
- ii = serial.available();
- logostream << "D serial.available = " << ii<< std::endl;
- serial.readString(buffer, '\n', 254, 1000);
- logostream << "D serial.readString = " << buffer << std::endl;
- // bytes_read = my_read(fd,sbuff,100);
- //printf("got: %s",sbuff);
- }
- //write the rest:
- // printf("writing final %i words\n",(program->dpos-i));
- printf("---- send ------\n");
- ii = serial.available();
- logostream << "D serial.available = " << ii<< std::endl;
- serial.readString(buffer, '\n', 254, 1000);
- logostream << "D serial.readString = " << buffer << std::endl;
- serial.writeBytes(&(program->data[i]),(program->dpos-i)*4);
- //this_thread::sleep_for(1000ms);
- sleep(1);
- ii = serial.available();
- logostream << "D serial.available = " << ii<< std::endl;
- serial.readString(buffer, '\n', 254, 1000);
- logostream << "D serial.readString = " << buffer << std::endl;
- // bytes_read = my_read(fd,sbuff,10000);
- // if (bytes_read > 0){
- // printf("duepp: got: %s",sbuff);
- // if (strstr(sbuff,"data received") != NULL){ // first two bytes are checksums
- // gettimeofday(&end_time,&tz);
- //
- // d_time=(end_time.tv_sec-start_time.tv_sec)*1e6
- // +(end_time.tv_usec-start_time.tv_usec);
- // // fprintf(stderr,"downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- // printf("duepp: downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- // check checksums
- // checksum_data(&c1,&c2,program->dpos,program->data);
- // sscanf(sbuff,"%i %i",&c1d,&c2d);
- // if (c1 != c1d || c2 != c2d) {
- // printf("duepp: checksums don't match! I calculate: %i %i, received: %i %i\n",c1&0xff,c2&0xff,c1d,c2d);
- // return -1;
- // }
- // // else printf("checksum match: %i %i, %i %i\n",c1&0xff, c2&0xff,c1d,c2d);
- // return 0;
- //
- //
- // printf("duepp: no response to sent program\n");
- // return -1;
- } //due_download_prog
- int due_download_prog_save_to_file(int fd,due_prog_t *program){
- char cbyte[3];
- char sbuff[BUFFLEN];
- unsigned char c1,c2;
- int c1d,c2d;
- int i,bytes_read;
- struct timeval start_time,end_time;
- struct timezone tz;
- double d_time;
- if (fd <= 0){
- printf("duepp: due_download: got invalid file descriptor (<=0) \n");
- return -1;
- }
- if (program->error != 0){
- printf("duepp: pulse program has an error flag set, will not download!\n");
- return -1;
- }
- if (program->state != STATE_FINALIZED){
- printf("duepp: WARNING. Program has not been finalized. If it contains any subroutines, bad things will happen.\n");
- }
- gettimeofday(&start_time,&tz);
- printf("duepp: Sending prog size: %i ",program->dpos);
- fflush(stdout);
- // write(fd,"D",1);
- // send data length, low byte, high byte
- cbyte[0] = 'D';
- cbyte[1] = program->dpos & 0xff;
- cbyte[2] = (program->dpos>>8)&0xff;
- write(fd,cbyte,3);
- bytes_read = my_read(fd,sbuff,5000);
- if (bytes_read > 0 ){
- printf("duepp: Got: %s",sbuff);
- if (strstr(sbuff,"size ok") == NULL){
- printf("duepp: didn't get size ok, aborting\n");
- //return -1;
- }
- }
- else{
- printf("duepp: no response to program size\n");
- //return -1;
- }
- // then data.
- printf("duepp: Sending program: \n");
- fflush(stdout);
- // first do 512 byte blocks: = 128 4-byte words
- for ( i = 0 ; i+128 < program->dpos ; i += 128){
- printf("due_download_prog_save_to_file : 512 byte block at pos: %i ",i);
- write(fd,&(program->data[i]),512);
- //bytes_read = my_read(fd,sbuff,100);
- //printf("got: %s",sbuff);
- }
- //write the rest:
- printf("due_download_prog_save_to_file : writing final %i words\n",(program->dpos-i));
- write(fd,&(program->data[i]),(program->dpos-i)*4);
- //write(fd,&data[i],dpos*4);
- //bytes_read = my_read(fd,sbuff,10000);
- if (bytes_read > 0){
- printf("duepp: got: %s",sbuff);
- if (strstr(sbuff,"data received") != NULL){ // first two bytes are checksums
- gettimeofday(&end_time,&tz);
- d_time=(end_time.tv_sec-start_time.tv_sec)*1e6
- +(end_time.tv_usec-start_time.tv_usec);
- // fprintf(stderr,"downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- printf("duepp: downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- // check checksums
- checksum_data(&c1,&c2,program->dpos,program->data);
- sscanf(sbuff,"%i %i",&c1d,&c2d);
- if (c1 != c1d || c2 != c2d) {
- printf("duepp: checksums don't match! I calculate: %i %i, received: %i %i\n",c1&0xff,c2&0xff,c1d,c2d);
- //return -1;
- }
- // else printf("checksum match: %i %i, %i %i\n",c1&0xff, c2&0xff,c1d,c2d);
- return 0;
- }
- }
- printf("duepp: no response to sent program\n");
- //return -1;
- } //due_download_prog_save_to_file
- int due_download_prog_save_to_file_command(int fd,due_prog_t *program)
- {
- char cbyte[3];
- char sbuff[BUFFLEN];
- unsigned char c1,c2;
- int c1d,c2d;
- int i,bytes_read;
- struct timeval start_time,end_time;
- struct timezone tz;
- double d_time;
- if (fd <= 0){
- printf("duepp: due_download_command: got invalid file descriptor (<=0) \n");
- return -1;
- }
- if (program->error != 0){
- printf("duepp: pulse program has an error flag set, will not download!\n");
- return -1;
- }
- if (program->state != STATE_FINALIZED){
- printf("duepp: WARNING. Program has not been finalized. If it contains any subroutines, bad things will happen.\n");
- }
- gettimeofday(&start_time,&tz);
- printf("duepp: Sending prog size: %i ",program->dpos);
- fflush(stdout);
- // write(fd,"D",1);
- // send data length, low byte, high byte
- cbyte[0] = 'D';
- cbyte[1] = program->dpos & 0xff;
- cbyte[2] = (program->dpos>>8)&0xff;
- write(fd,cbyte,3);
- bytes_read = my_read(fd,sbuff,5000);
- if (bytes_read > 0 ){
- printf("duepp: Got: %s",sbuff);
- if (strstr(sbuff,"size ok") == NULL){
- printf("duepp: didn't get size ok, aborting\n");
- //return -1;
- }
- }
- else{
- printf("duepp: no response to program size\n");
- //return -1;
- }
- } //due_download_prog_save_to_file_command
- int due_download_prog_save_to_file_data(int fd,due_prog_t *program)
- {
- char cbyte[3];
- char sbuff[BUFFLEN];
- unsigned char c1,c2;
- int c1d,c2d;
- int i,bytes_read;
- struct timeval start_time,end_time;
- struct timezone tz;
- double d_time;
- if (fd <= 0){
- printf("duepp: due_download: got invalid file descriptor (<=0) \n");
- return -1;
- }
- if (program->error != 0){
- printf("duepp: pulse program has an error flag set, will not download!\n");
- return -1;
- }
- if (program->state != STATE_FINALIZED){
- printf("duepp: WARNING. Program has not been finalized. If it contains any subroutines, bad things will happen.\n");
- }
- gettimeofday(&start_time,&tz);
- printf("duepp: Sending prog size: %i ",program->dpos);
- fflush(stdout);
- // write(fd,"D",1);
- // // send data length, low byte, high byte
- // cbyte[0] = 'D';
- // cbyte[1] = program->dpos & 0xff;
- // cbyte[2] = (program->dpos>>8)&0xff;
- // write(fd,cbyte,3);
- //
- // bytes_read = my_read(fd,sbuff,5000);
- // if (bytes_read > 0 ){
- // printf("duepp: Got: %s",sbuff);
- // if (strstr(sbuff,"size ok") == NULL){
- // printf("duepp: didn't get size ok, aborting\n");
- // //return -1;
- // }
- // }
- // else{
- //printf("duepp: no response to program size\n");
- //return -1;
- // }
- // then data.
- printf("duepp: Sending program: \n");
- fflush(stdout);
- // first do 512 byte blocks: = 128 4-byte words
- for ( i = 0 ; i+128 < program->dpos ; i += 128){
- printf("due_download_prog_save_to_file : 512 byte block at pos: %i ",i);
- write(fd,&(program->data[i]),512);
- //bytes_read = my_read(fd,sbuff,100);
- //printf("got: %s",sbuff);
- }
- //write the rest:
- printf("due_download_prog_save_to_file : writing final %i words\n",(program->dpos-i));
- write(fd,&(program->data[i]),(program->dpos-i)*4);
- //write(fd,&data[i],dpos*4);
- //bytes_read = my_read(fd,sbuff,10000);
- if (bytes_read > 0){
- printf("duepp: got: %s",sbuff);
- if (strstr(sbuff,"data received") != NULL){ // first two bytes are checksums
- gettimeofday(&end_time,&tz);
- d_time=(end_time.tv_sec-start_time.tv_sec)*1e6
- +(end_time.tv_usec-start_time.tv_usec);
- // fprintf(stderr,"downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- printf("duepp: downloaded %i bytes in: %.0f us\n",program->dpos*4,d_time);
- // check checksums
- checksum_data(&c1,&c2,program->dpos,program->data);
- sscanf(sbuff,"%i %i",&c1d,&c2d);
- if (c1 != c1d || c2 != c2d) {
- printf("duepp: checksums don't match! I calculate: %i %i, received: %i %i\n",c1&0xff,c2&0xff,c1d,c2d);
- //return -1;
- }
- // else printf("checksum match: %i %i, %i %i\n",c1&0xff, c2&0xff,c1d,c2d);
- return 0;
- }
- }
- printf("duepp: no response to sent program\n");
- //return -1;
- } //due_download_prog_save_to_file_data
- int due_run_program(int fd, char start_command){
- // start_command is e, E or R for software start, triggered start and restart (resume when final event is still running).
- int bytes_read;
- char sbuff[BUFFLEN];
- if (fd <= 0){
- printf("duepp: due_run: got invalid file descriptor\n");
- return -1;
- }
- printf("duepp: writing %c: ",start_command);
- write(fd,&start_command,1);
- bytes_read = my_read(fd,sbuff,25);
- if (bytes_read > 0 ){
- printf("duepp: Got: %s",sbuff);
- if (strncmp(sbuff,"Starting",8) == 0 || strncmp(sbuff,"Restarting",10) == 0)
- return 0;
- }
- return -1;
- }
- int due_wait_for_completion(int fd, int timeout){
- char sbuff[BUFFLEN];
- int bytes_read;
- if (fd <= 0){
- printf("duepp: due_wait_for_completion: got invalid file descriptor\n");
- return -1;
- }
- printf("duepp: waiting for completion: \n");
- fflush(stdout);
- bytes_read = my_read(fd,sbuff,timeout);
- if (bytes_read == -1) return -1; // woken by signal.
- if (bytes_read == 0) return 1; // timeout
- printf("duepp: Got: %s\n",sbuff);
- if (strncmp(sbuff,"Final Event started",19)==0) return 0;
- if (strncmp(sbuff,"Was interrupted",15)==0) return 2;
- return -1;
- }
- int due_interrupt_program(int fd){
- // don't read anything. Follow this with due_wait_for_completion.
- printf("duepp: writing K: ");
- write(fd,"K",1);
- return 0;
- }
- int due_get_status(int fd){
- char sbuff[BUFFLEN];
- int bytes_read;
- if (fd <= 0){
- printf("duepp: due_get_status: got invalid file descriptor\n");
- return -1;
- }
- printf("duepp: writing S: \n");
- write(fd,"S",1);
- bytes_read = my_read(fd,sbuff,100);
- if (bytes_read == 0) return -1; //
- printf("duepp: Got: %s\n",sbuff);
- return 0;
- }
- int due_write_dacs_now(int fd, unsigned int dac0,unsigned int dac1){
- unsigned int dval,bytes_read,i;
- char sbuff[BUFFLEN];
- char cbyte[5],*obytes;
- if (fd <= 0){
- printf("duepp: due_write_dacs_now: got invalid file descriptor\n");
- return -1;
- }
- dval = dac0 | dac1<<16 | 1<<28;
- // write(fd,"A",1);
- // write(fd,&dval,4);
- cbyte[0] = 'A';
- obytes = (char *) &dval;
- for (i=0;i<4;i++)
- cbyte[i+1] = obytes[i];
- write(fd,cbyte,5);
- bytes_read = my_read(fd,sbuff,100);
- if (bytes_read >0){
- printf("duepp: Got: %s\n",sbuff);
- if (strncmp(sbuff,"OK",2) == 0) return 0;
- }
- return -1;
- }
- int due_write_alt_now(int fd, unsigned int output){
- unsigned int bytes_read,i;
- char sbuff[BUFFLEN];
- char cbyte[5],*obytes;
- if (fd <= 0){
- printf("duepp: due_write_alt_now: got invalid file descriptor\n");
- return -1;
- }
- // write(fd,"P",1);
- // write(fd,&output,4);
- cbyte[0] = 'P';
- obytes = (char *) &output;
- for (i=0;i<4;i++)
- cbyte[i+1] = obytes[i];
- write(fd,cbyte,5);
- bytes_read = my_read(fd,sbuff,100);
- if (bytes_read >0){
- printf("duepp: Got: %s\n",sbuff);
- if (strncmp(sbuff,"OK",2) == 0) return 0;
- }
- return -1;
- }
- int due_read_analog(int fd, unsigned char pin){
- // pin number should be one of 62, 63, 64, 65 for A8-A11 (D62-D65 or B.17-B.20)
- unsigned int bytes_read;
- char sbuff[BUFFLEN];
- char cbyte[2];
- unsigned int rval=0;
- if (fd <= 0){
- printf("duepp: due_read_analog: got invalid file descriptor\n");
- return -1;
- }
- cbyte[0] = 'a';
- cbyte[1] = pin;
- write(fd,cbyte,2);
- bytes_read = my_read(fd,sbuff,100);
- if (bytes_read >0){
- rval = atoi(sbuff);
- // printf("duepp: Got: %s, converted to int: %i\n",sbuff,rval);
- }
- return rval;
- }
|