ECE4760 - Laser Projector (ipb7, jcc384, pfc38)  1
Raster Laser Projection
pt_cornell_1_2_1.h
Go to the documentation of this file.
1 /*
2  * File: pt_cornell_1_2_1.h
3  * Author: brl4
4  *
5  * Created on Sept 22, 2015
6  */
7 
8 /*
9  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the Institute nor the names of its contributors
21  * may be used to endorse or promote products derived from this software
22  * without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * This file is part of the Contiki operating system.
37  *
38  * Author: Adam Dunkels <adam@sics.se>
39  *
40  * $Id: pt.h,v 1.7 2006/10/02 07:52:56 adam Exp $
41  */
42 #include <plib.h>
56 #ifndef __PT_H__
57 #define __PT_H__
58 
60 //#include "lc.h"
62 
70 #ifdef DOXYGEN
71 
79 #define LC_INIT(lc)
80 
92 #define LC_SET(lc)
93 
104 #define LC_RESUME(lc)
105 
116 #define LC_END(lc)
117 
125 #endif /* DOXYGEN */
126 
127 //#ifndef __LC_H__
128 //#define __LC_H__
129 
130 
131 //#ifdef LC_INCLUDE
132 //#include LC_INCLUDE
133 //#else
134 
136 //#include "lc-switch.h"
138 
139 //#ifndef __LC_SWITCH_H__
140 //#define __LC_SWITCH_H__
141 
142 /* WARNING! lc implementation using switch() does not work if an
143  LC_SET() is done within another switch() statement! */
144 
146 /*
147 typedef unsigned short lc_t;
148 
149 #define LC_INIT(s) s = 0;
150 
151 #define LC_RESUME(s) switch(s) { case 0:
152 
153 #define LC_SET(s) s = __LINE__; case __LINE__:
154 
155 #define LC_END(s) }
156 
157 #endif /* __LC_SWITCH_H__ */
158 
161 //#endif /* LC_INCLUDE */
162 
163 //#endif /* __LC_H__ */
164 
168 //#include "lc-addrlabels.h"
171 
172 #ifndef __LC_ADDRLABELS_H__
173 #define __LC_ADDRLABELS_H__
174 
176 typedef void * lc_t;
177 
178 #define LC_INIT(s) s = NULL
179 
180 #define LC_RESUME(s) \
181  do { \
182  if(s != NULL) { \
183  goto *s; \
184  } \
185  } while(0)
186 
187 #define LC_CONCAT2(s1, s2) s1##s2
188 #define LC_CONCAT(s1, s2) LC_CONCAT2(s1, s2)
189 
190 #define LC_SET(s) \
191  do { \
192  LC_CONCAT(LC_LABEL, __LINE__): \
193  (s) = &&LC_CONCAT(LC_LABEL, __LINE__); \
194  } while(0)
195 
196 #define LC_END(s)
197 
198 #endif /* __LC_ADDRLABELS_H__ */
199 
200 
201 
203 struct pt {
205  int pri;
206 };
207 
208 #define PT_WAITING 0
209 #define PT_YIELDED 1
210 #define PT_EXITED 2
211 #define PT_ENDED 3
212 
230 #define PT_INIT(pt) LC_INIT((pt)->lc)
231 
250 #define PT_THREAD(name_args) char name_args
251 
265 #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
266 
277 #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
278  PT_INIT(pt); return PT_ENDED; }
279 
298 #define PT_WAIT_UNTIL(pt, condition) \
299  do { \
300  LC_SET((pt)->lc); \
301  if(!(condition)) { \
302  return PT_WAITING; \
303  } \
304  } while(0)
305 
317 #define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
318 
342 #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
343 
356 #define PT_SPAWN(pt, child, thread) \
357  do { \
358  PT_INIT((child)); \
359  PT_WAIT_THREAD((pt), (thread)); \
360  } while(0)
361 
379 #define PT_RESTART(pt) \
380  do { \
381  PT_INIT(pt); \
382  return PT_WAITING; \
383  } while(0)
384 
396 #define PT_EXIT(pt) \
397  do { \
398  PT_INIT(pt); \
399  return PT_EXITED; \
400  } while(0)
401 
421 #define PT_SCHEDULE(f) ((f) < PT_EXITED)
422 //#define PT_SCHEDULE(f) ((f))
423 
441 #define PT_YIELD(pt) \
442  do { \
443  PT_YIELD_FLAG = 0; \
444  LC_SET((pt)->lc); \
445  if(PT_YIELD_FLAG == 0) { \
446  return PT_YIELDED; \
447  } \
448  } while(0)
449 
461 #define PT_YIELD_UNTIL(pt, cond) \
462  do { \
463  PT_YIELD_FLAG = 0; \
464  LC_SET((pt)->lc); \
465  if((PT_YIELD_FLAG == 0) || !(cond)) { \
466  return PT_YIELDED; \
467  } \
468  } while(0)
469 
472 #endif /* __PT_H__ */
473 
474 #ifndef __PT_SEM_H__
475 #define __PT_SEM_H__
476 
477 //#include "pt.h"
478 
479 struct pt_sem {
480  unsigned int count;
481 };
482 
497 #define PT_SEM_INIT(s, c) (s)->count = c
498 
515 #define PT_SEM_WAIT(pt, s) \
516  do { \
517  PT_WAIT_UNTIL(pt, (s)->count > 0); \
518  --(s)->count; \
519  } while(0)
520 
536 #define PT_SEM_SIGNAL(pt, s) ++(s)->count
537 
538 #endif /* __PT_SEM_H__ */
539 
540 //=====================================================================
541 //=== BRL4 additions for PIC 32 =======================================
542 //=====================================================================
543 
544 // macro to time a thread execution interveal in millisec
545 // max time 4000 sec
546 //#include <plib.h>
547 //#include <limits.h>
548 //#include "config.h"
549 
550 #define PT_YIELD_TIME_msec(delay_time) \
551  do { static unsigned int time_thread ;\
552  time_thread = time_tick_millsec + (unsigned int)delay_time ; \
553  PT_YIELD_UNTIL(pt, (time_tick_millsec >= time_thread)); \
554  } while(0);
555 
556 // macro to return system time
557 #define PT_GET_TIME() (time_tick_millsec)
558 
559 // init rate sehcduler
560 //#define PT_INIT(pt, priority) LC_INIT((pt)->lc ; (pt)->pri = priority)
561 //PT_PRIORITY_INIT
562 #define PT_RATE_INIT() int pt_pri_count = 0;
563 // maitain proority frame count
564 //PT_PRIORITY_LOOP maitains a counter used to control execution
565 #define PT_RATE_LOOP() pt_pri_count = (pt_pri_count+1) & 0xf ;
566 // schecedule priority thread
567 //PT_PRIORITY_SCHEDULE
568 // 5 levels
569 // rate 0 is highest -- every time thru loop
570 // priority 1 -- every 2 times thru loop
571 // priority 2 -- every 4 times thru loop
572 // 3 is -- every 8 times thru loop
573 #define PT_RATE_SCHEDULE(f,rate) \
574  if((rate==0) | \
575  (rate==1 && ((pt_pri_count & 0b1)==0) ) | \
576  (rate==2 && ((pt_pri_count & 0b11)==0) ) | \
577  (rate==3 && ((pt_pri_count & 0b111)==0)) | \
578  (rate==4 && ((pt_pri_count & 0b1111)==0))) \
579  PT_SCHEDULE(f);
580 
581 // macro to use 4 bit DAC as debugger output
582 // level range 0-15; duration in microseconds
583 // -- with zero meaning HOLD it on forever
584 //while((signed int)ReadTimer45() <= time_hold){};
585 // time_hold = duration + ReadTimer45() ;
586 #define PT_DEBUG_VALUE(level, duration) \
587 do { static int i ; \
588  CVRCON = CVRCON_setup | (level & 0xf); \
589  if (duration>0){ \
590  for (i=0; i<duration*7; i++){};\
591  CVRCON = CVRCON_setup; \
592  } \
593 } while(0);
594 
595 // macros to manipulate a semaphore without blocking
596 #define PT_SEM_SET(s) (s)->count=1
597 #define PT_SEM_CLEAR(s) (s)->count=0
598 #define PT_SEM_READ(s) (s)->count
599 #define PT_SEM_ACCEPT(s) \
600  s->count; \
601  if (s->count) s->count-- ; \
602 
603 //====================================================================
604 //=== serial setup ===================================================
605 //#ifdef use_uart_serial
607 // UART parameters
608 
609 #define PB_DIVISOR (1 << OSCCONbits.PBDIV) // read the peripheral bus divider, FPBDIV
610 #define PB_FREQ sys_clock/PB_DIVISOR // periperhal bus frequency
611 #define clrscr() printf( "\x1b[2J")
612 #define home() printf( "\x1b[H")
613 #define pcr() printf( '\r')
614 #define crlf putchar(0x0a); putchar(0x0d);
615 #define backspace 0x7f // make sure your backspace matches this!
616 #define max_chars 64 // for input/output buffer
617 //====================================================================
618 // build a string from the UART2 /////////////
623 {
624  static char character;
625  // mark the beginnning of the input thread
626  PT_BEGIN(pt);
627 
628  num_char = 0;
629  //memset(term_buffer, 0, max_chars);
630 
631  while(num_char < max_chars)
632  {
633  // get the character
634  // yield until there is a valid character so that other
635  // threads can execute
636  PT_YIELD_UNTIL(pt, UARTReceivedDataIsAvailable(UART2));
637  // while(!UARTReceivedDataIsAvailable(UART2)){};
638  character = UARTGetDataByte(UART2);
639  PT_YIELD_UNTIL(pt, UARTTransmitterIsReady(UART2));
640  UARTSendDataByte(UART2, character);
641 
642  // unomment to check backspace character!!!
643  //printf("--%x--",character );
644 
645  // end line
646  if(character == '\r'){
647  PT_term_buffer[num_char] = 0; // zero terminate the string
648  //crlf; // send a new line
649  PT_YIELD_UNTIL(pt, UARTTransmitterIsReady(UART2));
650  UARTSendDataByte(UART2, '\n');
651  break;
652  }
653  // backspace
654  else if (character == backspace){
655  PT_YIELD_UNTIL(pt, UARTTransmitterIsReady(UART2));
656  UARTSendDataByte(UART2, ' ');
657  PT_YIELD_UNTIL(pt, UARTTransmitterIsReady(UART2));
658  UARTSendDataByte(UART2, backspace);
659  num_char--;
660  // check for buffer underflow
661  if (num_char<0) {num_char = 0 ;}
662  }
663  else {PT_term_buffer[num_char++] = character ;}
664  //if (character == backspace)
665 
666  } //end while(num_char < max_size)
667 
668  // kill this input thread, to allow spawning thread to execute
669  PT_EXIT(pt);
670  // and indicate the end of the thread
671  PT_END(pt);
672 }
673 
674 //====================================================================
675 // === send a string to the UART2 ====================================
678 int PutSerialBuffer(struct pt *pt)
679 {
680  PT_BEGIN(pt);
681  num_send_chars = 0;
682  while (PT_send_buffer[num_send_chars] != 0){
683  PT_YIELD_UNTIL(pt, UARTTransmitterIsReady(UART2));
684  UARTSendDataByte(UART2, PT_send_buffer[num_send_chars]);
685  num_send_chars++;
686  }
687  // kill this output thread, to allow spawning thread to execute
688  PT_EXIT(pt);
689  // and indicate the end of the thread
690  PT_END(pt);
691 }
692 
693 //====================================================================
694 // === DMA send string to the UART2 ==================================
696 {
697  PT_BEGIN(pt);
698  //mPORTBSetBits(BIT_0);
699  // check for null string
700  if (PT_send_buffer[0]==0)PT_EXIT(pt);
701  // sent the first character
702  PT_YIELD_UNTIL(pt, UARTTransmitterIsReady(UART2));
703  UARTSendDataByte(UART2, PT_send_buffer[0]);
704  //DmaChnStartTxfer(DMA_CHANNEL1, DMA_WAIT_NOT, 0);
705  // start the DMA
706  DmaChnEnable(DMA_CHANNEL1);
707  // wait for DMA done
708  //mPORTBClearBits(BIT_0);
709  PT_YIELD_UNTIL(pt, DmaChnGetEvFlags(DMA_CHANNEL1) & DMA_EV_BLOCK_DONE);
710  //wait until the transmit buffer is empty
711  PT_YIELD_UNTIL(pt, U2STA&0x100);
712 
713  // kill this output thread, to allow spawning thread to execute
714  PT_EXIT(pt);
715  // and indicate the end of the thread
716  PT_END(pt);
717 }
718 //#endif //#ifdef use_uart_serial
719 
720 //======================================================================
721 // vref confing (if used)
723 
724 // system time
725 volatile unsigned int time_tick_millsec ;
726 
727 // Timer 5 interrupt handler ///////
728 // ipl2 means "interrupt priority level 2"
729 void __ISR(_TIMER_5_VECTOR, IPL2AUTO) Timer5Handler(void) //_TIMER_5_VECTOR
730 {
731  // clear the interrupt flag
732  mT5ClearIntFlag();
733  //count milliseconds
735 }
736 
737 void PT_setup (void)
738 {
739  // Configure the device for maximum performance but do not change the PBDIV
740  // Given the options, this function will change the flash wait states, RAM
741  // wait state and enable prefetch cache but will not change the PBDIV.
742  // The PBDIV value is already set via the pragma FPBDIV option above..
743  SYSTEMConfig(sys_clock, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
744 
745  ANSELA =0; //make sure analog is cleared
746  ANSELB =0;
747 
748 #ifdef use_uart_serial
749  // === init the uart2 ===================
750  PPSInput (2, U2RX, RPB11); //Assign U2RX to pin RPB11 -- Physical pin 22 on 28 PDIP
751  PPSOutput(4, RPB10, U2TX); //Assign U2TX to pin RPB10 -- Physical pin 21 on 28 PDIP
752  UARTConfigure(UART2, UART_ENABLE_PINS_TX_RX_ONLY);
753  UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
754  UARTSetDataRate(UART2, pb_clock, BAUDRATE);
755  UARTEnable(UART2, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
756  printf("\n\r..protothreads start..\n\r");
757  // === set up DMA for UART output =========
758  // configure the channel and enable end-on-match
759  DmaChnOpen(DMA_CHANNEL1, DMA_CHN_PRI2, DMA_OPEN_MATCH);
760  // trigger a byte everytime the UART is empty
761  DmaChnSetEventControl(DMA_CHANNEL1, DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN|DMA_EV_START_IRQ(_UART2_TX_IRQ));
762  // source and destination
763  DmaChnSetTxfer(DMA_CHANNEL1, PT_send_buffer+1, (void*)&U2TXREG, max_chars, 1, 1);
764  // signal when done
765  DmaChnSetEvEnableFlags(DMA_CHANNEL1, DMA_EV_BLOCK_DONE);
766  // set null as ending character (of a string)
767  DmaChnSetMatchPattern(DMA_CHANNEL1, 0x00);
768 #endif //#ifdef use_uart_serial
769 
770  // ===Set up timer5 ======================
771  // timer 5: on, interrupts, internal clock,
772  // set up to count millsec
773  OpenTimer5(T5_ON | T5_SOURCE_INT | T5_PS_1_1 , pb_clock/1000);
774  // set up the timer interrupt with a priority of 2
775  ConfigIntTimer5(T5_INT_ON | T5_INT_PRIOR_2);
776  mT5ClearIntFlag(); // and clear the interrupt flag
777  // zero the system time tick
778  time_tick_millsec = 0;
779 
780  //=== Set up VREF as a debugger output =======
781  #ifdef use_vref_debug
782  // set up the Vref pin and use as a DAC
783  // enable module| eanble output | use low range output | use internal reference | desired step
784  CVREFOpen( CVREF_ENABLE | CVREF_OUTPUT_ENABLE | CVREF_RANGE_LOW | CVREF_SOURCE_AVDD | CVREF_STEP_0 );
785  // And read back setup from CVRCON for speed later
786  // 0x8060 is enabled with output enabled, Vdd ref, and 0-0.6(Vdd) range
787  CVRCON_setup = CVRCON; //CVRCON = 0x8060 from Tahmid http://tahmidmc.blogspot.com/
788 
789 #endif //#ifdef use_vref_debug
790 
791 }
#define sys_clock
Definition: config.h:35
#define PT_YIELD_UNTIL(pt, cond)
Yield from the protothread until a condition occurs.
int CVRCON_setup
void * lc_t
#define backspace
int PT_GetSerialBuffer(struct pt *pt)
lc_t lc
int PT_DMA_PutSerialBuffer(struct pt *pt)
void __ISR(_TIMER_5_VECTOR, IPL2AUTO) Timer5Handler(void)
volatile unsigned int time_tick_millsec
#define pb_clock
Definition: config.h:38
#define PT_EXIT(pt)
char PT_term_buffer[max_chars]
#define PT_END(pt)
void PT_setup(void)
#define max_chars
int num_send_chars
#define PT_BEGIN(pt)
unsigned int count
char PT_send_buffer[max_chars]
int PutSerialBuffer(struct pt *pt)
int num_char