updated app-templates
[apps/agl-service-unicens.git] / ucs2-vol / src / device_container.cpp
1 /*
2  * libmostvolume example
3  *
4  * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * You may also obtain this software under a propriety license from Microchip.
20  * Please contact Microchip for further information.
21  *
22  */
23
24 #include "device_container.h"
25 #include "callbacks.h"
26 #include "ucs_api.h"
27
28 #define DEVCONT_TIME_RETRIGGER      (uint16_t)100U
29 #define DEVCONT_TIME_NOW            (uint16_t)0U
30 #define DEVCONT_TIME_STOP           (uint16_t)0xFFFFU
31
32 #define DEVCONT_UNUSED(a)     (a = a)
33
34 CDeviceContainer::CDeviceContainer()
35 {
36     this->_idx_processing = 0U;
37     this->_ucs_inst_ptr = NULL;
38     this->_values_pptr = NULL;
39     this->_values_sz = 0U;
40     this->_tx_busy = false;
41     this->_service_requested = false;
42     this->_service_fptr = NULL;
43 }
44
45 CDeviceContainer::~CDeviceContainer()
46 {
47     Clb_RegisterI2CResultCB(NULL, NULL);    /* avoid that the result callback is fired after object is destroyed */
48 }
49
50 void CDeviceContainer::RegisterValues(CDeviceValue** list_pptr, uint16_t list_sz)
51 {
52     this->_idx_processing = 0U;
53     this->_values_pptr = list_pptr;
54     this->_values_sz = list_sz;
55     this->_tx_busy = false;
56
57     if ((list_pptr != NULL) && (list_sz > 0U))
58     {
59         this->_idx_processing = list_sz - 1U;
60     }
61 }
62
63 void CDeviceContainer::ClearValues()
64 {
65     this->_idx_processing = 0U;
66     this->_values_pptr = NULL;
67     this->_values_sz = 0U;
68     this->_tx_busy = false;
69 }
70
71 void CDeviceContainer::SetValue(uint16_t key, uint8_t value)
72 {
73      uint16_t idx;
74      bool req_update = false;
75
76      for (idx = 0U; idx < this->_values_sz; idx++)
77      {
78          if (this->_values_pptr[idx]->GetKey() == key)
79          {
80             this->_values_pptr[idx]->SetValue(value);
81             if (this->_values_pptr[idx]->RequiresUpdate())
82             {
83                 req_update = true;
84             }
85          }
86      }
87
88     if (req_update && (!this->_tx_busy))
89     {
90         RequestService(DEVCONT_TIME_NOW); //fire callback
91     }
92 }
93
94 void CDeviceContainer::IncrementProcIndex(void)
95 {
96     if ((_idx_processing + 1U) >=  this->_values_sz)
97     {
98         _idx_processing = 0U;
99     }
100     else
101     {
102         _idx_processing++;
103     }
104 }
105
106 // starts at latest position, searches next value to update, waits until response
107 void CDeviceContainer::Update()
108 {
109     uint16_t cnt;
110     bool error = false;
111     _service_requested = false;
112
113     if (this->_ucs_inst_ptr == NULL)
114     {
115         return;
116     }
117
118     if (this->_tx_busy)
119     {
120         return;
121     }
122     
123     for (cnt = 0u; cnt < this->_values_sz; cnt++)   /* just run one cycle */
124     {
125         IncrementProcIndex();
126
127         if (_values_pptr[_idx_processing]->RequiresUpdate())
128         {
129             if (_values_pptr[_idx_processing]->FireUpdateMessage())
130             {
131                 Clb_RegisterI2CResultCB(&OnI2cResult, this);
132                 this->_tx_busy = true;
133                 break;
134             }
135             else
136             {
137                 error = true;
138             }
139         }
140     }
141
142     if (error)
143     {
144         RequestService(DEVCONT_TIME_RETRIGGER);
145     }
146 }
147
148 void CDeviceContainer::HandleI2cResult(Ucs_I2c_Result_t result)
149 {
150     DEVCONT_UNUSED(result);
151     this->_tx_busy = false;
152     this->RequestService(DEVCONT_TIME_NOW);
153 }
154
155 void CDeviceContainer::OnI2cResult(Ucs_I2c_Result_t result, void *obj_ptr)
156 {
157     ((CDeviceContainer*)obj_ptr)->HandleI2cResult(result);
158 }
159
160 void CDeviceContainer::RequestService(uint16_t timeout)
161 {
162     if (!_service_requested)
163     {
164         _service_requested = true;
165
166         if (_service_fptr != NULL)
167         {
168             _service_fptr(timeout);
169         }
170     }
171 }