MotorWare f2806x Module API Documentation
hal_both.h
Go to the documentation of this file.
1 #ifndef _HAL_H_
2 #define _HAL_H_
3 /* --COPYRIGHT--,BSD
4  * Copyright (c) 2012, Texas Instruments Incorporated
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * * Neither the name of Texas Instruments Incorporated nor the names of
19  * its contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
26  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  * --/COPYRIGHT--*/
34 
40 
41 
42 // **************************************************************************
43 // the includes
44 
45 
46 // modules
47 
48 
49 // platforms
50 #include "hal_obj.h"
51 
52 
57 
58 
59 
60 #ifdef __cplusplus
61 extern "C" {
62 #endif
63 
64 
65 // **************************************************************************
66 // the defines
67 
69 #define DRV8301_SPI
70 
71 #define Device_cal (void (*)(void))0x3D7C80
72 
75 #define FP_SCALE 32768
76 
78 #define FP_ROUND FP_SCALE/2
79 
83 #define OSC_POSTRIM 32
84 #define OSC_POSTRIM_OFF FP_SCALE*OSC_POSTRIM
85 
87 
89 #define getOsc1FineTrimSlope() (*(int16_t (*)(void))0x3D7E90)()
90 
92 #define getOsc1FineTrimOffset() (*(int16_t (*)(void))0x3D7E93)()
93 
95 #define getOsc1CoarseTrim() (*(int16_t (*)(void))0x3D7E96)()
96 
99 #define getOsc2FineTrimSlope() (*(int16_t (*)(void))0x3D7E99)()
100 
102 #define getOsc2FineTrimOffset() (*(int16_t (*)(void))0x3D7E9C)()
103 
105 #define getOsc2CoarseTrim() (*(int16_t (*)(void))0x3D7E9F)()
106 
108 #define getRefTempOffset() (*(int16_t (*)(void))0x3D7EA2)()
109 
112 #define HAL_PWM_DBFED_CNT 1
113 
114 
117 #define HAL_PWM_DBRED_CNT 1
118 
119 
122 #define HAL_turnLedOff HAL_setGpioLow
123 
124 
127 #define HAL_turnLedOn HAL_setGpioHigh
128 
129 
132 #define HAL_toggleLed HAL_toggleGpio
133 
134 
135 // **************************************************************************
136 // the typedefs
137 
138 
141 typedef enum
142 {
146 
147 
150 typedef enum
151 {
152  HAL_Gpio_LED2=GPIO_Number_34,
153  HAL_Gpio_LED3=GPIO_Number_39
155 
156 
159 typedef enum
160 {
164 
165 
166 // **************************************************************************
167 // the globals
168 
169 extern interrupt void mainISR(void);
170 
171 
172 // **************************************************************************
173 // the function prototypes
174 
175 
180 static inline void HAL_acqAdcInt(HAL_Handle handle,const ADC_IntNumber_e intNumber)
181 {
182  HAL_Obj *obj = (HAL_Obj *)handle;
183 
184 
185  // clear the ADC interrupt flag
186  ADC_clearIntFlag(obj->adcHandle,intNumber);
187 
188 
189  // Acknowledge interrupt from PIE group 10
190  PIE_clearInt(obj->pieHandle,PIE_GroupNumber_10);
191 
192  return;
193 } // end of HAL_acqAdcInt() function
194 
195 
200 static inline void HAL_acqPwmInt(HAL_Handle handle,const PWM_Number_e pwmNumber)
201 {
202  HAL_Obj *obj = (HAL_Obj *)handle;
203 
204 
205  // clear the PWM interrupt flag
206  PWM_clearIntFlag(obj->pwmHandle[pwmNumber]);
207 
208 
209  // clear the SOCA flag
210  PWM_clearSocAFlag(obj->pwmHandle[pwmNumber]);
211 
212 
213  // Acknowledge interrupt from PIE group 3
214  PIE_clearInt(obj->pieHandle,PIE_GroupNumber_3);
215 
216  return;
217 } // end of HAL_acqPwmInt() function
218 
219 
223 static inline void HAL_acqTimer0Int(HAL_Handle handle)
224 {
225  HAL_Obj *obj = (HAL_Obj *)handle;
226 
227 
228  // clear the Timer 0 interrupt flag
229  TIMER_clearFlag(obj->timerHandle[0]);
230 
231 
232  // Acknowledge interrupt from PIE group 1
233  PIE_clearInt(obj->pieHandle,PIE_GroupNumber_1);
234 
235  return;
236 } // end of HAL_acqTimer0Int() function
237 
238 
244 extern void HAL_cal(HAL_Handle handle);
245 
246 
249 extern void HAL_disableGlobalInts(HAL_Handle handle);
250 
251 
254 extern void HAL_disableWdog(HAL_Handle handle);
255 
256 
261 static inline void HAL_disablePwm(HAL_Handle handle)
262 {
263  HAL_Obj *obj = (HAL_Obj *)handle;
264 
265  PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_1]);
266  PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_2]);
267  PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_3]);
268 
269  return;
270 } // end of HAL_disablePwm() function
271 
272 
277 extern void HAL_enableAdcInts(HAL_Handle handle);
278 
279 
285 extern void HAL_enableDebugInt(HAL_Handle handle);
286 
287 
290 extern void HAL_enableGlobalInts(HAL_Handle handle);
291 
292 
296 extern void HAL_enableDrv(HAL_Handle handle);
297 
298 
303 static inline void HAL_enablePwm(HAL_Handle handle)
304 {
305  HAL_Obj *obj = (HAL_Obj *)handle;
306 
307  PWM_clearOneShotTrip(obj->pwmHandle[PWM_Number_1]);
308  PWM_clearOneShotTrip(obj->pwmHandle[PWM_Number_2]);
309  PWM_clearOneShotTrip(obj->pwmHandle[PWM_Number_3]);
310 
311  return;
312 } // end of HAL_enablePwm() function
313 
314 
317 extern void HAL_enablePwmInt(HAL_Handle handle);
318 
319 
322 extern void HAL_enableTimer0Int(HAL_Handle handle);
323 
324 
329 static inline ADC_SocSampleDelay_e HAL_getAdcSocSampleDelay(HAL_Handle handle,
330  const ADC_SocNumber_e socNumber)
331 {
332  HAL_Obj *obj = (HAL_Obj *)handle;
333 
334  return(ADC_getSocSampleDelay(obj->adcHandle,socNumber));
335 } // end of HAL_getAdcSocSampleDelay() function
336 
337 
346 static inline _iq HAL_getBias(HAL_Handle handle,
347  const HAL_SensorType_e sensorType,
348  uint_least8_t sensorNumber)
349 {
350  HAL_Obj *obj = (HAL_Obj *)handle;
351  _iq bias = _IQ(0.0);
352 
353  if(sensorType == HAL_SensorType_Current)
354  {
355  bias = obj->adcBias.I.value[sensorNumber];
356  }
357  else if(sensorType == HAL_SensorType_Voltage)
358  {
359  bias = obj->adcBias.V.value[sensorNumber];
360  }
361 
362  return(bias);
363 } // end of HAL_getBias() function
364 
365 
374 {
375  HAL_Obj *obj = (HAL_Obj *)handle;
376 
377  return(obj->current_sf);
378 } // end of HAL_getCurrentScaleFactor() function
379 
380 
384 static inline uint_least8_t HAL_getNumCurrentSensors(HAL_Handle handle)
385 {
386  HAL_Obj *obj = (HAL_Obj *)handle;
387 
388 
389  return(obj->numCurrentSensors);
390 } // end of HAL_getNumCurrentSensors() function
391 
392 
396 static inline uint_least8_t HAL_getNumVoltageSensors(HAL_Handle handle)
397 {
398  HAL_Obj *obj = (HAL_Obj *)handle;
399 
400 
401  return(obj->numVoltageSensors);
402 } // end of HAL_getNumVoltageSensors() function
403 
404 
413  const HAL_SensorType_e sensorType,
414  const uint_least8_t sensorNumber)
415 {
416  HAL_Obj *obj = (HAL_Obj *)handle;
417 
418  _iq beta_lp_pu = _IQ(0.0);
419 
420  if(sensorType == HAL_SensorType_Current)
421  {
422  beta_lp_pu = OFFSET_getBeta(obj->offsetHandle_I[sensorNumber]);
423  }
424  else if(sensorType == HAL_SensorType_Voltage)
425  {
426  beta_lp_pu = OFFSET_getBeta(obj->offsetHandle_V[sensorNumber]);
427  }
428 
429  return(beta_lp_pu);
430 } // end of HAL_getOffsetBeta_lp_pu() function
431 
432 
440 static inline _iq HAL_getOffsetValue(HAL_Handle handle,
441  const HAL_SensorType_e sensorType,
442  const uint_least8_t sensorNumber)
443 {
444  HAL_Obj *obj = (HAL_Obj *)handle;
445 
446  _iq offset = _IQ(0.0);
447 
448  if(sensorType == HAL_SensorType_Current)
449  {
450  offset = OFFSET_getOffset(obj->offsetHandle_I[sensorNumber]);
451  }
452  else if(sensorType == HAL_SensorType_Voltage)
453  {
454  offset = OFFSET_getOffset(obj->offsetHandle_V[sensorNumber]);
455  }
456 
457  return(offset);
458 } // end of HAL_getOffsetValue() function
459 
460 
469 {
470  HAL_Obj *obj = (HAL_Obj *)handle;
471 
472  return(obj->voltage_sf);
473 } // end of HAL_getVoltageScaleFactor() function
474 
475 
482 extern void HAL_setupFaults(HAL_Handle handle);
483 
484 
491 extern HAL_Handle HAL_init(void *pMemory,const size_t numBytes);
492 
493 
497 static inline void HAL_initIntVectorTable(HAL_Handle handle)
498  {
499  HAL_Obj *obj = (HAL_Obj *)handle;
500  PIE_Obj *pie = (PIE_Obj *)obj->pieHandle;
501 
502 
503  ENABLE_PROTECTED_REGISTER_WRITE_MODE;
504 
505  pie->ADCINT1 = &mainISR;
506 
507  DISABLE_PROTECTED_REGISTER_WRITE_MODE;
508 
509  return;
510  } // end of HAL_initIntVectorTable() function
511 
512 
520 static inline void HAL_readAdcData(HAL_Handle handle,HAL_AdcData_t *pAdcData)
521 {
522  HAL_Obj *obj = (HAL_Obj *)handle;
523 
524  _iq value;
525  _iq current_sf = HAL_getCurrentScaleFactor(handle);
526  _iq voltage_sf = HAL_getVoltageScaleFactor(handle);
527 
528 
529  // convert current A
530  // sample the first sample twice due to errata sprz342f, ignore the first sample
531  value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_1);
532  value = _IQ12mpy(value,current_sf) - obj->adcBias.I.value[0]; // divide by 2^numAdcBits = 2^12
533  pAdcData->I.value[0] = value;
534 
535  // convert current B
536  value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_2);
537  value = _IQ12mpy(value,current_sf) - obj->adcBias.I.value[1]; // divide by 2^numAdcBits = 2^12
538  pAdcData->I.value[1] = value;
539 
540  // convert current C
541  value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_3);
542  value = _IQ12mpy(value,current_sf) - obj->adcBias.I.value[2]; // divide by 2^numAdcBits = 2^12
543  pAdcData->I.value[2] = value;
544 
545  // convert voltage A
546  value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_4);
547  value = _IQ12mpy(value,voltage_sf) - obj->adcBias.V.value[0]; // divide by 2^numAdcBits = 2^12
548  pAdcData->V.value[0] = value;
549 
550  // convert voltage B
551  value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_5);
552  value = _IQ12mpy(value,voltage_sf) - obj->adcBias.V.value[1]; // divide by 2^numAdcBits = 2^12
553  pAdcData->V.value[1] = value;
554 
555  // convert voltage C
556  value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_6);
557  value = _IQ12mpy(value,voltage_sf) - obj->adcBias.V.value[2]; // divide by 2^numAdcBits = 2^12
558  pAdcData->V.value[2] = value;
559 
560  // read the dcBus voltage value
561  value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_7); // divide by 2^numAdcBits = 2^12
562  value = _IQ12mpy(value,voltage_sf);
563  pAdcData->dcBus = value;
564 
565  return;
566 } // end of HAL_readAdcData() function
567 
568 
573 static inline uint32_t HAL_readTimerCnt(HAL_Handle handle,const uint_least8_t timerNumber)
574 {
575  HAL_Obj *obj = (HAL_Obj *)handle;
576  uint32_t timerCnt = TIMER_getCount(obj->timerHandle[timerNumber]);
577 
578  return(timerCnt);
579 } // end of HAL_readTimerCnt() function
580 
581 
585 static inline void HAL_reloadTimer(HAL_Handle handle,const uint_least8_t timerNumber)
586 {
587  HAL_Obj *obj = (HAL_Obj *)handle;
588 
589  // reload the specified timer
590  TIMER_reload(obj->timerHandle[timerNumber]);
591 
592  return;
593 } // end of HAL_reloadTimer() function
594 
595 
598 void HAL_setupGate(HAL_Handle handle);
599 
600 
604 static inline void HAL_startTimer(HAL_Handle handle,const uint_least8_t timerNumber)
605 {
606  HAL_Obj *obj = (HAL_Obj *)handle;
607 
608  // start the specified timer
609  TIMER_start(obj->timerHandle[timerNumber]);
610 
611  return;
612 } // end of HAL_startTimer() function
613 
614 
618 static inline void HAL_stopTimer(HAL_Handle handle,const uint_least8_t timerNumber)
619 {
620  HAL_Obj *obj = (HAL_Obj *)handle;
621 
622  // stop the specified timer
623  TIMER_stop(obj->timerHandle[timerNumber]);
624 
625  return;
626 } // end of HAL_stopTimer() function
627 
628 
633 static inline void HAL_setTimerPeriod(HAL_Handle handle,const uint_least8_t timerNumber, const uint32_t period)
634 {
635  HAL_Obj *obj = (HAL_Obj *)handle;
636 
637  // set the period
638  TIMER_setPeriod(obj->timerHandle[timerNumber], period);
639 
640  return;
641 } // end of HAL_setTimerPeriod() function
642 
643 
648 static inline uint32_t HAL_getTimerPeriod(HAL_Handle handle,const uint_least8_t timerNumber)
649 {
650  HAL_Obj *obj = (HAL_Obj *)handle;
651 
652  uint32_t timerPeriod = TIMER_getPeriod(obj->timerHandle[timerNumber]);
653 
654  return(timerPeriod);
655 } // end of HAL_getTimerPeriod() function
656 
657 
662 static inline void HAL_setAdcSocSampleDelay(HAL_Handle handle,
663  const ADC_SocNumber_e socNumber,
664  const ADC_SocSampleDelay_e sampleDelay)
665 {
666  HAL_Obj *obj = (HAL_Obj *)handle;
667 
668  ADC_setSocSampleDelay(obj->adcHandle,socNumber,sampleDelay);
669 
670  return;
671 } // end of HAL_setAdcSocSampleDelay() function
672 
673 
679 static inline void HAL_setBias(HAL_Handle handle,
680  const HAL_SensorType_e sensorType,
681  uint_least8_t sensorNumber,
682  const _iq bias)
683 {
684  HAL_Obj *obj = (HAL_Obj *)handle;
685 
686 
687  if(sensorType == HAL_SensorType_Current)
688  {
689  obj->adcBias.I.value[sensorNumber] = bias;
690  }
691  else if(sensorType == HAL_SensorType_Voltage)
692  {
693  obj->adcBias.V.value[sensorNumber] = bias;
694  }
695 
696  return;
697 } // end of HAL_setBias() function
698 
699 
705 static inline void HAL_setGpioHigh(HAL_Handle handle,const GPIO_Number_e gpioNumber)
706 {
707  HAL_Obj *obj = (HAL_Obj *)handle;
708 
709 
710  // set GPIO high
711  GPIO_setHigh(obj->gpioHandle,gpioNumber);
712 
713  return;
714 } // end of HAL_setGpioHigh() function
715 
716 
721 static inline bool HAL_readGpio(HAL_Handle handle,const GPIO_Number_e gpioNumber)
722 {
723  HAL_Obj *obj = (HAL_Obj *)handle;
724 
725  // read GPIO
726  return(GPIO_read(obj->gpioHandle,gpioNumber));
727 } // end of HAL_readGpio() function
728 
729 
735 static inline void HAL_toggleGpio(HAL_Handle handle,const GPIO_Number_e gpioNumber)
736 {
737  HAL_Obj *obj = (HAL_Obj *)handle;
738 
739 
740  // set GPIO high
741  GPIO_toggle(obj->gpioHandle,gpioNumber);
742 
743  return;
744 } // end of HAL_setGpioHigh() function
745 
746 
752 static inline void HAL_setGpioLow(HAL_Handle handle,const GPIO_Number_e gpioNumber)
753 {
754  HAL_Obj *obj = (HAL_Obj *)handle;
755 
756 
757  // set GPIO low
758  GPIO_setLow(obj->gpioHandle,gpioNumber);
759 
760  return;
761 } // end of HAL_setGpioLow() function
762 
763 
767 static inline void HAL_setCurrentScaleFactor(HAL_Handle handle,const _iq current_sf)
768 {
769  HAL_Obj *obj = (HAL_Obj *)handle;
770 
771 
772  obj->current_sf = current_sf;
773 
774  return;
775 } // end of HAL_setCurrentScaleFactor() function
776 
777 
781 static inline void HAL_setNumCurrentSensors(HAL_Handle handle,const uint_least8_t numCurrentSensors)
782 {
783  HAL_Obj *obj = (HAL_Obj *)handle;
784 
785 
786  obj->numCurrentSensors = numCurrentSensors;
787 
788  return;
789 } // end of HAL_setNumCurrentSensors() function
790 
791 
795 static inline void HAL_setNumVoltageSensors(HAL_Handle handle,const uint_least8_t numVoltageSensors)
796 {
797  HAL_Obj *obj = (HAL_Obj *)handle;
798 
799 
800  obj->numVoltageSensors = numVoltageSensors;
801 
802  return;
803 } // end of HAL_setNumVoltageSensors() function
804 
805 
811 static inline void HAL_setOffsetBeta_lp_pu(HAL_Handle handle,
812  const HAL_SensorType_e sensorType,
813  const uint_least8_t sensorNumber,
814  const _iq beta_lp_pu)
815 {
816  HAL_Obj *obj = (HAL_Obj *)handle;
817 
818  if(sensorType == HAL_SensorType_Current)
819  {
820  OFFSET_setBeta(obj->offsetHandle_I[sensorNumber],beta_lp_pu);
821  }
822  else if(sensorType == HAL_SensorType_Voltage)
823  {
824  OFFSET_setBeta(obj->offsetHandle_V[sensorNumber],beta_lp_pu);
825  }
826 
827  return;
828 } // end of HAL_setOffsetBeta_lp_pu() function
829 
830 
836 static inline void HAL_setOffsetInitCond(HAL_Handle handle,
837  const HAL_SensorType_e sensorType,
838  const uint_least8_t sensorNumber,
839  const _iq initCond)
840 {
841  HAL_Obj *obj = (HAL_Obj *)handle;
842 
843  if(sensorType == HAL_SensorType_Current)
844  {
845  OFFSET_setInitCond(obj->offsetHandle_I[sensorNumber],initCond);
846  }
847  else if(sensorType == HAL_SensorType_Voltage)
848  {
849  OFFSET_setInitCond(obj->offsetHandle_V[sensorNumber],initCond);
850  }
851 
852  return;
853 } // end of HAL_setOffsetInitCond() function
854 
855 
861 static inline void HAL_setOffsetValue(HAL_Handle handle,
862  const HAL_SensorType_e sensorType,
863  const uint_least8_t sensorNumber,
864  const _iq value)
865 {
866  HAL_Obj *obj = (HAL_Obj *)handle;
867 
868  if(sensorType == HAL_SensorType_Current)
869  {
870  OFFSET_setOffset(obj->offsetHandle_I[sensorNumber],value);
871  }
872  else if(sensorType == HAL_SensorType_Voltage)
873  {
874  OFFSET_setOffset(obj->offsetHandle_V[sensorNumber],value);
875  }
876 
877  return;
878 } // end of HAL_setOffsetValue() function
879 
880 
884 static inline void HAL_setVoltageScaleFactor(HAL_Handle handle,const _iq voltage_sf)
885 {
886  HAL_Obj *obj = (HAL_Obj *)handle;
887 
888  obj->voltage_sf = voltage_sf;
889 
890  return;
891 } // end of HAL_setVoltageScaleFactor() function
892 
893 
900 extern void HAL_setParams(HAL_Handle handle,const USER_Params *pUserParams);
901 
902 
905 extern void HAL_setupAdcs(HAL_Handle handle);
906 
907 
911 extern void HAL_setupClks(HAL_Handle handle);
912 
913 
915 extern void HAL_setupFlash(HAL_Handle handle);
916 
917 
920 extern void HAL_setupGpios(HAL_Handle handle);
921 
922 
925 extern void HAL_setupPeripheralClks(HAL_Handle handle);
926 
927 
930 extern void HAL_setupPie(HAL_Handle handle);
931 
932 
936 extern void HAL_setupPll(HAL_Handle handle,const PLL_ClkFreq_e clkFreq);
937 
938 
944 extern void HAL_setupPwms(HAL_Handle handle,
945  const float_t systemFreq_MHz,
946  const float_t pwmPeriod_usec,
947  const uint_least16_t numPwmTicksPerIsrTick);
948 
949 
952 extern void HAL_setupPwmDacs(HAL_Handle handle);
953 
954 
957 extern void HAL_setupSpiA(HAL_Handle handle);
958 
959 
962 extern void HAL_setupSpiB(HAL_Handle handle);
963 
964 
968 void HAL_setupTimers(HAL_Handle handle,const float_t systemFreq_MHz);
969 
970 
975 static inline void HAL_updateAdcBias(HAL_Handle handle)
976 {
977  uint_least8_t cnt;
978  HAL_Obj *obj = (HAL_Obj *)handle;
979  _iq bias;
980 
981 
982  // update the current bias
983  for(cnt=0;cnt<HAL_getNumCurrentSensors(handle);cnt++)
984  {
985  bias = HAL_getBias(handle,HAL_SensorType_Current,cnt);
986 
987  bias += OFFSET_getOffset(obj->offsetHandle_I[cnt]);
988 
989  HAL_setBias(handle,HAL_SensorType_Current,cnt,bias);
990  }
991 
992 
993  // update the voltage bias
994  for(cnt=0;cnt<HAL_getNumVoltageSensors(handle);cnt++)
995  {
996  bias = HAL_getBias(handle,HAL_SensorType_Voltage,cnt);
997 
998  bias += OFFSET_getOffset(obj->offsetHandle_V[cnt]);
999 
1000  HAL_setBias(handle,HAL_SensorType_Voltage,cnt,bias);
1001  }
1002 
1003  return;
1004 } // end of HAL_updateAdcBias() function
1005 
1006 
1010 static inline void HAL_writeDacData(HAL_Handle handle,HAL_DacData_t *pDacData)
1011 {
1012  HAL_Obj *obj = (HAL_Obj *)handle;
1013 
1014  // convert values from _IQ to _IQ15
1015  int16_t dacValue_1 = (int16_t)_IQtoIQ15(pDacData->value[0]);
1016  int16_t dacValue_2 = (int16_t)_IQtoIQ15(pDacData->value[1]);
1017  int16_t dacValue_3 = (int16_t)_IQtoIQ15(pDacData->value[2]);
1018  int16_t dacValue_4 = (int16_t)_IQtoIQ15(pDacData->value[3]);
1019 
1020  // write the DAC data
1021  PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_1],dacValue_1);
1022  PWMDAC_write_CmpB(obj->pwmDacHandle[PWMDAC_Number_1],dacValue_2);
1023  PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_2],dacValue_3);
1024  PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_2],dacValue_4);
1025 
1026  return;
1027 } // end of HAL_writeDacData() function
1028 
1029 
1033 static inline void HAL_writePwmData(HAL_Handle handle,HAL_PwmData_t *pPwmData)
1034 {
1035  uint_least8_t cnt;
1036  HAL_Obj *obj = (HAL_Obj *)handle;
1037  PWM_Obj *pwm;
1038  _iq period;
1039  _iq pwmData_neg;
1040  _iq pwmData_sat;
1041  _iq pwmData_sat_dc;
1042  _iq value;
1043  uint16_t value_sat;
1044 
1045  for(cnt=0;cnt<3;cnt++)
1046  {
1047  pwm = (PWM_Obj *)obj->pwmHandle[cnt];
1048  period = (_iq)pwm->TBPRD;
1049  pwmData_neg = _IQmpy(pPwmData->Tabc.value[cnt],_IQ(-1.0));
1050  pwmData_sat = _IQsat(pwmData_neg,_IQ(0.5),_IQ(-0.5));
1051  pwmData_sat_dc = pwmData_sat + _IQ(0.5);
1052  value = _IQmpy(pwmData_sat_dc, period);
1053  value_sat = (uint16_t)_IQsat(value, period, _IQ(0.0));
1054 
1055  // write the PWM data
1056  PWM_write_CmpA(obj->pwmHandle[cnt],value_sat);
1057  }
1058 
1059  return;
1060 } // end of HAL_writePwmData() function
1061 
1062 
1067 static inline uint16_t HAL_readPwmCmpA(HAL_Handle handle,const PWM_Number_e pwmNumber)
1068 {
1069  HAL_Obj *obj = (HAL_Obj *)handle;
1070 
1071  // the compare value to be returned
1072  uint16_t pwmValue;
1073 
1074  pwmValue = PWM_get_CmpA(obj->pwmHandle[pwmNumber]);
1075 
1076  return(pwmValue);
1077 } // end of HAL_readPwmCmpA() function
1078 
1079 
1084 static inline uint16_t HAL_readPwmCmpB(HAL_Handle handle,const PWM_Number_e pwmNumber)
1085 {
1086  HAL_Obj *obj = (HAL_Obj *)handle;
1087 
1088  // the compare value to be returned
1089  uint16_t pwmValue;
1090 
1091  pwmValue = PWM_get_CmpB(obj->pwmHandle[pwmNumber]);
1092 
1093  return(pwmValue);
1094 } // end of HAL_readPwmCmpB() function
1095 
1096 
1101 static inline uint16_t HAL_readPwmPeriod(HAL_Handle handle,const PWM_Number_e pwmNumber)
1102 {
1103  HAL_Obj *obj = (HAL_Obj *)handle;
1104 
1105  // the period value to be returned
1106  uint16_t pwmPeriodValue;
1107 
1108  pwmPeriodValue = PWM_getPeriod(obj->pwmHandle[pwmNumber]);
1109 
1110  return(pwmPeriodValue);
1111 } // end of HAL_readPwmPeriod() function
1112 
1113 
1114 static inline void HAL_setTrigger(HAL_Handle handle,const int16_t minwidth)
1115 {
1116  HAL_Obj *obj = (HAL_Obj *)handle;
1117  PWM_Obj *pwm1 = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
1118  PWM_Obj *pwm2 = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
1119  PWM_Obj *pwm3 = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
1120  PWM_Obj *pwm;
1121  bool ignorepwm1 = false;
1122  bool ignorepwm2 = false;
1123  bool ignorepwm3 = false;
1124 
1125  uint16_t nextPulse1 = (pwm1->CMPA + pwm1->CMPAM) / 2;
1126  uint16_t nextPulse2 = (pwm2->CMPA + pwm2->CMPAM) / 2;
1127  uint16_t nextPulse3 = (pwm3->CMPA + pwm3->CMPAM) / 2;
1128  uint16_t minNextPulse;
1129 
1130  if(nextPulse1 < minwidth) ignorepwm1 = true;
1131  if(nextPulse2 < minwidth) ignorepwm2 = true;
1132  if(nextPulse3 < minwidth) ignorepwm3 = true;
1133 
1134  if((ignorepwm1 == false) && (ignorepwm2 == false) && (ignorepwm3 == false))
1135  {
1136  minNextPulse = nextPulse1;
1137  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
1138 
1139  if(minNextPulse > nextPulse2)
1140  {
1141  minNextPulse = nextPulse2;
1142  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
1143  }
1144 
1145  if(minNextPulse > nextPulse3)
1146  {
1147  minNextPulse = nextPulse3;
1148  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
1149  }
1150  }
1151  else if((ignorepwm1 == false) && (ignorepwm2 == false) && (ignorepwm3 == true))
1152  {
1153  minNextPulse = nextPulse1;
1154  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
1155 
1156  if(minNextPulse > nextPulse2)
1157  {
1158  minNextPulse = nextPulse2;
1159  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
1160  }
1161  }
1162  else if((ignorepwm1 == false) && (ignorepwm2 == true) && (ignorepwm3 == false))
1163  {
1164  minNextPulse = nextPulse1;
1165  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
1166 
1167  if(minNextPulse > nextPulse3)
1168  {
1169  minNextPulse = nextPulse3;
1170  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
1171  }
1172  }
1173  else if((ignorepwm1 == false) && (ignorepwm2 == true) && (ignorepwm3 == true))
1174  {
1175  minNextPulse = nextPulse1;
1176  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
1177  }
1178  else if((ignorepwm1 == true) && (ignorepwm2 == false) && (ignorepwm3 == false))
1179  {
1180  minNextPulse = nextPulse2;
1181  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
1182 
1183  if(minNextPulse > nextPulse3)
1184  {
1185  minNextPulse = nextPulse3;
1186  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
1187  }
1188  }
1189  else if((ignorepwm1 == true) && (ignorepwm2 == false) && (ignorepwm3 == true))
1190  {
1191  minNextPulse = nextPulse2;
1192  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
1193  }
1194  else if((ignorepwm1 == true) && (ignorepwm2 == true) && (ignorepwm3 == false))
1195  {
1196  minNextPulse = nextPulse3;
1197  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
1198  }
1199  else
1200  {
1201  minNextPulse = nextPulse1;
1202  pwm = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
1203  }
1204 
1205  if(pwm->CMPAM >= (pwm->CMPA + pwm->DBFED))
1206  {
1207  pwm1->CMPB = (pwm->CMPAM - (pwm->CMPA + pwm->DBFED)) / 2 + 1;
1208  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBDecr);
1209  }
1210  else
1211  {
1212  pwm1->CMPB = ((pwm->CMPA + pwm->DBFED) - pwm->CMPAM) / 2 + 1;
1213  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBIncr);
1214  }
1215 
1216  return;
1217 } // end of HAL_setTrigger() function
1218 
1219 
1223 void HAL_AdcCalChanSelect(HAL_Handle handle, const ADC_SocChanNumber_e chanNumber);
1224 
1225 
1229 uint16_t HAL_AdcCalConversion(HAL_Handle handle);
1230 
1231 
1234 void HAL_AdcOffsetSelfCal(HAL_Handle handle);
1235 
1236 
1242 uint16_t HAL_getOscTrimValue(int16_t coarse, int16_t fine);
1243 
1244 
1247 void HAL_OscTempComp(HAL_Handle handle);
1248 
1249 
1252 void HAL_osc1Comp(HAL_Handle handle, const int16_t sensorSample);
1253 
1254 
1257 void HAL_osc2Comp(HAL_Handle handle, const int16_t sensorSample);
1258 
1259 
1263 void HAL_writeDrvData(HAL_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars);
1264 
1265 
1269 void HAL_readDrvData(HAL_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars);
1270 
1271 
1275 void HAL_setupDrvSpi(HAL_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars);
1276 
1277 
1278 #ifdef __cplusplus
1279 }
1280 #endif // extern "C"
1281 
1283 #endif // end of _HAL_H_ definition
1284 
1285 
OFFSET_Handle offsetHandle_I[3]
the handles for the current offset estimators
static void HAL_acqTimer0Int(HAL_Handle handle)
Acknowledges an interrupt from Timer 0 so that another Timer 0 interrupt can happen again...
Definition: hal_both.h:223
void HAL_enableGlobalInts(HAL_Handle handle)
Enables global interrupts.
void HAL_enableAdcInts(HAL_Handle handle)
Enables the ADC interrupts.
static bool HAL_readGpio(HAL_Handle handle, const GPIO_Number_e gpioNumber)
Reads the specified GPIO pin.
Definition: hal_both.h:721
static uint_least8_t HAL_getNumCurrentSensors(HAL_Handle handle)
Gets the number of current sensors.
Definition: hal_both.h:384
void HAL_disableGlobalInts(HAL_Handle handle)
Disables global interrupts.
#define _IQtoIQ15(A)
static _iq HAL_getVoltageScaleFactor(HAL_Handle handle)
Gets the voltage scale factor.
Definition: hal_both.h:468
static void HAL_setBias(HAL_Handle handle, const HAL_SensorType_e sensorType, uint_least8_t sensorNumber, const _iq bias)
Sets the ADC bias value.
Definition: hal_both.h:679
#define _IQ(A)
static void HAL_setNumVoltageSensors(HAL_Handle handle, const uint_least8_t numVoltageSensors)
Sets the number of voltage sensors.
Definition: hal_both.h:795
Select QEP2.
Definition: hal_both.h:144
void HAL_OscTempComp(HAL_Handle handle)
Executes the oscillator 1 and 2 calibration functions.
static uint16_t HAL_readPwmCmpB(HAL_Handle handle, const PWM_Number_e pwmNumber)
Reads PWM compare register B.
Definition: hal_both.h:1084
_iq value[3]
Definition: 32b/math.h:261
interrupt void mainISR(void)
void HAL_writeDrvData(HAL_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars)
Writes data to the driver.
static void HAL_setTrigger(HAL_Handle handle, const int16_t minwidth)
Definition: hal_both.h:1114
GPIO pin number for LaunchPad LED D10.
Definition: hal_both.h:153
static void HAL_setGpioLow(HAL_Handle handle, const GPIO_Number_e gpioNumber)
Sets the GPIO pin low.
Definition: hal_both.h:752
static void HAL_setCurrentScaleFactor(HAL_Handle handle, const _iq current_sf)
Sets the current scale factor in the hardware abstraction layer.
Definition: hal_both.h:767
static void HAL_updateAdcBias(HAL_Handle handle)
Updates the ADC bias values.
Definition: hal_both.h:975
Defines a structure for the user parameters.
void HAL_AdcCalChanSelect(HAL_Handle handle, const ADC_SocChanNumber_e chanNumber)
Selects the analog channel used for calibration.
_iq current_sf
the current scale factor, amps_pu/cnt
HAL_QepSelect_e
Enumeration for the QEP setup.
Definition: hal_both.h:141
void HAL_setupPeripheralClks(HAL_Handle handle)
Sets up the peripheral clocks.
HAL_SensorType_e
Enumeration for the sensor types.
Definition: hal_both.h:159
Select QEP1.
Definition: hal_both.h:143
static uint16_t HAL_readPwmCmpA(HAL_Handle handle, const PWM_Number_e pwmNumber)
Reads PWM compare register A.
Definition: hal_both.h:1067
void HAL_setupTimers(HAL_Handle handle, const float_t systemFreq_MHz)
Sets up the timers.
void HAL_osc2Comp(HAL_Handle handle, const int16_t sensorSample)
Executes the oscillator 2 calibration based on input sample.
long _iq
void HAL_setupPll(HAL_Handle handle, const PLL_ClkFreq_e clkFreq)
Sets up the PLL (Phase Lock Loop)
HAL_AdcData_t adcBias
the ADC bias
static void HAL_writePwmData(HAL_Handle handle, HAL_PwmData_t *pPwmData)
Writes PWM data to the PWM comparators for motor control.
Definition: hal_both.h:1033
Enumeration for current sensor.
Definition: hal_both.h:161
void HAL_setupGpios(HAL_Handle handle)
Sets up the GPIO (General Purpose I/O) pins.
static uint32_t HAL_readTimerCnt(HAL_Handle handle, const uint_least8_t timerNumber)
Reads the timer count.
Definition: hal_both.h:573
static void HAL_acqPwmInt(HAL_Handle handle, const PWM_Number_e pwmNumber)
Acknowledges an interrupt from the PWM so that another PWM interrupt can happen again.
Definition: hal_both.h:200
void HAL_setupFlash(HAL_Handle handle)
Sets up the FLASH.
void OFFSET_setInitCond(OFFSET_Handle handle, const _iq initCond)
Set the initial condition of the integrator or the value of y[n-1].
Definition: 32b/offset.c:102
static void HAL_disablePwm(HAL_Handle handle)
Disables the PWM device.
Definition: hal_both.h:261
void HAL_enablePwmInt(HAL_Handle handle)
Enables the PWM interrupt.
void HAL_setupClks(HAL_Handle handle)
Sets up the clocks.
static void HAL_setGpioHigh(HAL_Handle handle, const GPIO_Number_e gpioNumber)
Sets the GPIO pin high.
Definition: hal_both.h:705
void HAL_setupFaults(HAL_Handle handle)
Configures the fault protection logic.
MATH_vec3 Tabc
the PWM time-durations for each motor phase
#define _IQmpy(A, B)
static void HAL_writeDacData(HAL_Handle handle, HAL_DacData_t *pDacData)
Writes DAC data to the PWM comparators for DAC (digital-to-analog conversion) output.
Definition: hal_both.h:1010
#define _IQ12mpy(A, B)
void HAL_enableDrv(HAL_Handle handle)
Enables the 8301 device.
void HAL_osc1Comp(HAL_Handle handle, const int16_t sensorSample)
Executes the oscillator 1 calibration based on input sample.
static _iq HAL_getCurrentScaleFactor(HAL_Handle handle)
Gets the current scale factor.
Definition: hal_both.h:373
void OFFSET_setOffset(OFFSET_Handle handle, _iq offsetValue)
Sets the offset value.
Definition: 32b/offset.c:113
uint_least8_t numCurrentSensors
the number of current sensors
void HAL_setupDrvSpi(HAL_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars)
Sets up the SPI interface for the driver.
void HAL_setupPwms(HAL_Handle handle, const float_t systemFreq_MHz, const float_t pwmPeriod_usec, const uint_least16_t numPwmTicksPerIsrTick)
Sets up the PWMs (Pulse Width Modulators)
void HAL_setupPie(HAL_Handle handle)
Sets up the PIE (Peripheral Interrupt Expansion)
void HAL_enableDebugInt(HAL_Handle handle)
Enables the debug interrupt.
static void HAL_setAdcSocSampleDelay(HAL_Handle handle, const ADC_SocNumber_e socNumber, const ADC_SocSampleDelay_e sampleDelay)
Sets the ADC SOC sample delay value.
Definition: hal_both.h:662
static void HAL_setVoltageScaleFactor(HAL_Handle handle, const _iq voltage_sf)
Sets the voltage scale factor in the hardware abstraction layer.
Definition: hal_both.h:884
static void HAL_setTimerPeriod(HAL_Handle handle, const uint_least8_t timerNumber, const uint32_t period)
Sets the timer period.
Definition: hal_both.h:633
static void HAL_stopTimer(HAL_Handle handle, const uint_least8_t timerNumber)
Stops the timer.
Definition: hal_both.h:618
static void HAL_initIntVectorTable(HAL_Handle handle)
Initializes the interrupt vector table.
Definition: hal_both.h:497
_iq voltage_sf
the voltage scale factor, volts_pu/cnt
static uint_least8_t HAL_getNumVoltageSensors(HAL_Handle handle)
Gets the number of voltage sensors.
Definition: hal_both.h:396
static void HAL_setOffsetValue(HAL_Handle handle, const HAL_SensorType_e sensorType, const uint_least8_t sensorNumber, const _iq value)
Sets the initial offset value for offset estimation.
Definition: hal_both.h:861
void HAL_setupSpiB(HAL_Handle handle)
Sets up the spiB peripheral.
static void HAL_reloadTimer(HAL_Handle handle, const uint_least8_t timerNumber)
Reloads the timer.
Definition: hal_both.h:585
void HAL_AdcOffsetSelfCal(HAL_Handle handle)
Executes the offset calibration of the ADC.
static ADC_SocSampleDelay_e HAL_getAdcSocSampleDelay(HAL_Handle handle, const ADC_SocNumber_e socNumber)
Gets the ADC delay value.
Definition: hal_both.h:329
void OFFSET_setBeta(OFFSET_Handle handle, const _iq beta)
Sets the beta offset filter coefficient.
Definition: 32b/offset.c:88
ADC_Handle adcHandle
the ADC handle
HAL_Handle HAL_init(void *pMemory, const size_t numBytes)
Initializes the hardware abstraction layer (HAL) object.
static uint32_t HAL_getTimerPeriod(HAL_Handle handle, const uint_least8_t timerNumber)
Gets the timer period.
Definition: hal_both.h:648
static void HAL_toggleGpio(HAL_Handle handle, const GPIO_Number_e gpioNumber)
Toggles the GPIO pin.
Definition: hal_both.h:735
static uint16_t HAL_readPwmPeriod(HAL_Handle handle, const PWM_Number_e pwmNumber)
Reads PWM period register.
Definition: hal_both.h:1101
void HAL_cal(HAL_Handle handle)
Executes calibration routines.
void HAL_setupGate(HAL_Handle handle)
Sets up the GATE object.
static void HAL_acqAdcInt(HAL_Handle handle, const ADC_IntNumber_e intNumber)
Acknowledges an interrupt from the ADC so that another ADC interrupt can happen again.
Definition: hal_both.h:180
_iq OFFSET_getBeta(OFFSET_Handle handle)
Gets the beta offset filter coefficient.
Definition: 32b/offset.c:58
static _iq HAL_getOffsetValue(HAL_Handle handle, const HAL_SensorType_e sensorType, const uint_least8_t sensorNumber)
Gets the offset value.
Definition: hal_both.h:440
Enumeration for voltage sensor.
Definition: hal_both.h:162
uint16_t HAL_AdcCalConversion(HAL_Handle handle)
Reads the converted value from the selected calibration channel.
void HAL_setupPwmDacs(HAL_Handle handle)
Sets up the PWM DACs (Pulse Width Modulator Digital to Analof Converters)
GPIO pin number for LaunchPad LED D9.
Definition: hal_both.h:152
uint16_t HAL_getOscTrimValue(int16_t coarse, int16_t fine)
Converts coarse and fine oscillator trim values into a single 16bit word value.
#define _IQsat(A, Pos, Neg)
static void HAL_startTimer(HAL_Handle handle, const uint_least8_t timerNumber)
Starts the timer.
Definition: hal_both.h:604
static void HAL_setOffsetBeta_lp_pu(HAL_Handle handle, const HAL_SensorType_e sensorType, const uint_least8_t sensorNumber, const _iq beta_lp_pu)
Sets the value used to set the low pass filter pole for offset estimation.
Definition: hal_both.h:811
void HAL_setupSpiA(HAL_Handle handle)
Sets up the spiA peripheral.
void HAL_setParams(HAL_Handle handle, const USER_Params *pUserParams)
Sets the hardware abstraction layer parameters.
void HAL_readDrvData(HAL_Handle handle, DRV_SPI_8301_Vars_t *Spi_8301_Vars)
Reads data from the driver.
static void HAL_enablePwm(HAL_Handle handle)
Enables the PWM devices.
Definition: hal_both.h:303
static void HAL_setNumCurrentSensors(HAL_Handle handle, const uint_least8_t numCurrentSensors)
Sets the number of current sensors.
Definition: hal_both.h:781
static _iq HAL_getBias(HAL_Handle handle, const HAL_SensorType_e sensorType, uint_least8_t sensorNumber)
Gets the ADC bias value.
Definition: hal_both.h:346
void HAL_setupAdcs(HAL_Handle handle)
Sets up the ADCs (Analog to Digital Converters)
uint_least8_t numVoltageSensors
the number of voltage sensors
void HAL_enableTimer0Int(HAL_Handle handle)
Enables the Timer 0 interrupt.
HAL_LedNumber_e
Enumeration for the LED numbers.
Definition: hal_both.h:150
void HAL_disableWdog(HAL_Handle halHandle)
Disables the watch dog.
OFFSET_Handle offsetHandle_V[3]
the handles for the voltage offset estimators
static _iq OFFSET_getOffset(OFFSET_Handle handle)
Gets the offset value.
Definition: 32b/offset.h:115
static void HAL_readAdcData(HAL_Handle handle, HAL_AdcData_t *pAdcData)
Reads the ADC data.
Definition: hal_both.h:520
static _iq HAL_getOffsetBeta_lp_pu(HAL_Handle handle, const HAL_SensorType_e sensorType, const uint_least8_t sensorNumber)
Gets the value used to set the low pass filter pole for offset estimation.
Definition: hal_both.h:412
float float_t
Defines the portable data type for 32 bit, signed floating-point data.
Definition: types.h:121
Defines the hardware abstraction layer (HAL) data.
static void HAL_setOffsetInitCond(HAL_Handle handle, const HAL_SensorType_e sensorType, const uint_least8_t sensorNumber, const _iq initCond)
Sets the offset initial condition value for offset estimation.
Definition: hal_both.h:836
GPIO_Handle gpioHandle
the GPIO handle