forked from EffectiveRange/fw-mrhat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
260 lines (210 loc) · 7.74 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
* MAIN Generated Driver File
*
* @file main.c
*
* @defgroup main MAIN
*
* @brief This is the generated driver implementation file for the MAIN driver.
*
* @version MAIN Driver Version 1.0.0
*/
/*
© [2023] Microchip Technology Inc. and its subsidiaries.
Subject to your compliance with these terms, you may use Microchip
software and any derivatives exclusively with Microchip products.
You are responsible for complying with 3rd party license terms
applicable to your use of 3rd party software (including open source
software) that may accompany Microchip software. SOFTWARE IS ?AS IS.?
NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS
SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP?S
TOTAL LIABILITY ON ALL CLAIMS RELATED TO THE SOFTWARE WILL NOT
EXCEED AMOUNT OF FEES, IF ANY, YOU PAID DIRECTLY TO MICROCHIP FOR
THIS SOFTWARE.
*/
#include "mcc_generated_files/system/system.h"
#include "mcc_generated_files/i2c_host/i2c1_multimode.h"
#include "tasks.h"
#include "onoff.h"
#include "power_mgr.h"
#include "shutdown_mgr.h"
/*
Main application
*/
extern void MiliSecTimerOverflow();
#define I2C_CLIENT_LOCATION_SIZE 10
//Private functions
bool Client_Application(i2c_client_transfer_event_t event);
//reg 0 FW id
//reg1 IRQ reg
// bit0: shallow shut
// bit1: deep shutdown reg
//reg2 STAT
// bit0: battery_available
//reg 3 BTN_STAT
//reg 4
//irq test, number of button long press count
//0x55 means shutdown is requested from PIC
// reg5
//PI will fill it to sign shutdown request has been acknowledged
//0xAA means PI has acked shutdown req
//reg 9 i2c error state
//value of i2c_client_error_t enum
// Private variable
volatile uint8_t CLIENT_DATA[I2C_CLIENT_LOCATION_SIZE] = {
0x55, 0x01, 0x02, 0x03, 0, 0x05, 0x06, 0x07, 0x08, 0x09
};
volatile static uint8_t clientLocation = 0x00;
volatile static bool isClientLocation = false;
bool Client_Application(i2c_client_transfer_event_t event) {
switch (event) {
case I2C_CLIENT_TRANSFER_EVENT_ADDR_MATCH: //Address Match Event
if (I2C1_Client.TransferDirGet() == I2C_CLIENT_TRANSFER_DIR_WRITE) {
isClientLocation = true;
}
break;
case I2C_CLIENT_TRANSFER_EVENT_RX_READY: //Read the data sent by I2C Host
if (isClientLocation) {
clientLocation = I2C1_Client.ReadByte();
isClientLocation = false;
break;
} else {
CLIENT_DATA[clientLocation++] = I2C1_Client.ReadByte();
if (clientLocation >= I2C_CLIENT_LOCATION_SIZE) {
clientLocation = 0x00;
}
}
break;
case I2C_CLIENT_TRANSFER_EVENT_TX_READY: //Provide the Client data requested by the I2C Host
I2C1_Client.WriteByte(CLIENT_DATA[clientLocation++]);
if (clientLocation >= I2C_CLIENT_LOCATION_SIZE) {
clientLocation = 0x00;
}
break;
case I2C_CLIENT_TRANSFER_EVENT_STOP_BIT_RECEIVED: //Stop Communication
clientLocation = 0x00;
break;
case I2C_CLIENT_TRANSFER_EVENT_ERROR: //Error Event Handler
clientLocation = 0x00;
i2c_client_error_t errorState = I2C1_Client.ErrorGet();
CLIENT_DATA[9] = errorState;
if (errorState == I2C_CLIENT_ERROR_BUS_COLLISION) {
// Bus Collision Error Handling
} else if (errorState == I2C_CLIENT_ERROR_WRITE_COLLISION) {
// Write Collision Error Handling
} else if (errorState == I2C_CLIENT_ERROR_RECEIVE_OVERFLOW) {
// Receive Overflow Error Handling
} else if (errorState == I2C_CLIENT_ERROR_TRANSMIT_UNDERFLOW) {
// Transmit Underflow Error Handling
} else if (errorState == I2C_CLIENT_ERROR_READ_UNDERFLOW) {
// Read Underflow Error Handling
}
break;
default:
break;
}
return true;
}
static uint8_t regAddrBuff[] = {0x18};
static uint8_t regAddrBuff2[] = {0x38};
static uint8_t readBuff[] = {0x00};
void process_device_id() {
__delay_ms(10);
}
void retry_read_device_id(void);
void read_device_id(volatile struct TaskDescr* taskd) {
uint8_t* addr = (uint8_t*) taskd->task_state;
if (!I2C1_WriteRead(0x6b, addr, 1, readBuff, 1)) {
return;
}
suspend_task(TASK_I2C_WAKEUP);
I2C1_Host_ReadyCallbackRegister(process_device_id);
I2C1_Host_CallbackRegister(retry_read_device_id);
}
void retry_read_device_id(void) {
if (I2C1_ErrorGet() == I2C_ERROR_BUS_COLLISION) {
resume_task(TASK_I2C_WAKEUP);
}
}
static int client_mode = 0;
static int host_mode = 0;
void switch_i2c_mode(volatile struct TaskDescr* taskd) {
if (taskd->task_state == &client_mode) {
I2C1_Switch_Mode(I2C1_CLIENT_MODE);
I2C1_Client.CallbackRegister(Client_Application);
} else {
I2C1_Switch_Mode(I2C1_HOST_MODE);
}
rm_task(TASK_I2C_SWITCH_MODE);
}
void OnOffSwithcPressed(enum ONOFFTypes type) {
CLIENT_DATA[3]=type;
switch (type) {
case BTN_1L:
ShutdownButtonPressed();
break;
case BTN_1S_1L:
//wake up pi
// MCU_INT_N_SetHigh();
// if (I2C1_Current_Mode() == I2C1_HOST_MODE) {
// add_task(TASK_I2C_WAKEUP, read_device_id, regAddrBuff2);
// }
// I2C_SEL_N_Toggle();
break;
case BTN_1S_1S_1L:
add_task(TASK_POWER_IC_SYSTEM_RESET,PowMgrSystemReset,NULL);
// if (I2C1_Current_Mode() == I2C1_HOST_MODE) {
// add_task(TASK_I2C_WAKEUP, read_device_id, regAddrBuff2);
// }
break;
};
}
volatile uint64_t pi_run_last_falling_time_ms=0;
void PIRunModeChanged() {
if(!PI_RUN_GetValue()){
//save last fall time
pi_run_last_falling_time_ms = GetTimeMs();
}
// if (PI_RUN_GetValue()) {
// add_task(TASK_I2C_SWITCH_MODE, switch_i2c_mode, &client_mode);
// } else {
// //remove PI from I2C bus
// add_task(TASK_I2C_SWITCH_MODE, switch_i2c_mode, &host_mode);
// I2C_SEL_N_SetLow(); //enable pi i2c
// }
}
int main(){
SYSTEM_Initialize();
// If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
// If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts
// Use the following macros to:
TASKS_Initialize();
ONOFF_Initialize();
ONOFF_CallbackRegister(OnOffSwithcPressed);
//enable PI RUN pin irq
PI_RUN_SetInterruptHandler(PIRunModeChanged);
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptHighEnable();
INTERRUPT_GlobalInterruptLowEnable();
// Disable the Global Interrupts
//INTERRUPT_GlobalInterruptDisable();
//1msec freerunngin timer irq
TMR1_OverflowCallbackRegister(MiliSecTimerOverflow);
//go to host mode
I2C1_Switch_Mode(I2C1_HOST_MODE);
//set charge enable when battery is present
PowMgrEnableDisableCharging();
//init shutdown mgr
ShutdownMgrInit();
//go back to client mode
I2C1_Switch_Mode(I2C1_CLIENT_MODE);
I2C1_Client.CallbackRegister(Client_Application);
I2C_SEL_N_SetHigh(); //enable pi i2c bus
run_tasks();
return 0;
}