1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include <stdint.h>
6 
7 #include "amp_config.h"
8 #include "amp_defines.h"
9 #include "aos_hal_gpio.h"
10 #include "aos_system.h"
11 #include "amp_task.h"
12 #include "board_mgr.h"
13 #include "quickjs.h"
14 #include "quickjs_addon_common.h"
15 
16 #define MOD_STR "ONEWIRE"
17 
18 /*
19 使用方法:yaml文件中添加JSE_HW_ADDON_ONEWIRE、JSE_HW_ADDON_GPIO、RHINO_CONFIG_HW_COUNT
20 参考如下:
21 def_config:                              # 组件的可配置项
22     CONFIG_ENGINE_DUKTAPE: 1
23     #CONFIG_ENGINE_QUICKJS: 1
24     CONFIG_VERSION: '1.0'
25     JSE_HW_ADDON_ONEWIRE: 1
26     JSE_HW_ADDON_GPIO: 1
27     RHINO_CONFIG_HW_COUNT: 1
28 
29 */
30 static int A,B,C,D,E,F,G,H,I,J;
31 static uint16_t gpio_init_flag = 0;
32 static JSClassID js_onewire_class_id;
33 
34 #define RHINO_CONFIG_HW_COUNT 1
35 
36 #if (RHINO_CONFIG_HW_COUNT > 0)
37 #define CONFIG_FAST_SYSTICK_HZ      (hal_cmu_get_crystal_freq() / 4)
38 #define FAST_TICKS_TO_US(tick)      ((uint32_t)(tick) * 10 / (CONFIG_FAST_SYSTICK_HZ / 1000 / 100))
39 
40 #define RHINO_CPU_INTRPT_DISABLE() do{ cpsr = cpu_intrpt_save(); }while(0)
41 #define RHINO_CPU_INTRPT_ENABLE()  do{ cpu_intrpt_restore(cpsr); }while(0)
42 
43 static JSClassID js_onewire_class_id;
44 
oneWireUdelay(unsigned long x)45 void oneWireUdelay(unsigned long x) {
46     unsigned long now,t;
47     int cpsr;
48 
49     RHINO_CPU_INTRPT_DISABLE();
50 
51     t = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
52     now = t;
53     while ((now - t) < x) {
54         now = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
55     }
56 
57     RHINO_CPU_INTRPT_ENABLE();
58 }
59 #endif
60 
oneWireGpioSet(gpio_dev_t * gpio_device,unsigned char leve)61 static void oneWireGpioSet(gpio_dev_t *gpio_device, unsigned char leve)
62 {
63     int ret = 0;
64 
65     if(leve == 1)
66     {
67         ret = aos_hal_gpio_output_high(gpio_device);
68     }
69     else if(leve == 0)
70     {
71          ret = aos_hal_gpio_output_low(gpio_device);
72 
73     }
74     //amp_warn(MOD_STR, "GPIO:%d, output config:0x%x, leve: %d, ret:%d", gpio_device->port, gpio_device->config, leve, ret);
75 }
76 
oneWireGpioGet(gpio_dev_t * gpio_device)77 static uint32_t oneWireGpioGet(gpio_dev_t *gpio_device)
78 {
79     int ret = 0;
80     unsigned int value = 0;
81 
82     ret = aos_hal_gpio_input_get(gpio_device, &value);
83     //amp_warn(MOD_STR, "GPIO:%d, input config:0x%x, ret: %d, value:%d\r\n", gpio_device->port, gpio_device->config, ret, value);
84 
85     return (ret == 0)? value: ret;
86 }
87 
88 //-----------------------------------------------------------------------------
89 // Generate a 1-Wire reset, return 1 if no presence detect was found,
90 // return 0 otherwise.
91 // (NOTE: Does not handle alarm presence from DS2404/DS1994)
92 //
oneWireTouchReset(gpio_dev_t * gpio_device)93 int oneWireTouchReset(gpio_dev_t *gpio_device)
94 {
95     int result1;
96     int result2;
97 
98     oneWireUdelay(G);
99 
100     oneWireGpioSet(gpio_device, 0x00); // Drives DQ low
101 
102     oneWireUdelay(H);
103 
104     oneWireGpioSet(gpio_device, 0x01); // Releases the bus
105 
106     oneWireUdelay(I);
107 
108     result1 = oneWireGpioGet(gpio_device) ^ 0x01; // Sample for presence pulse from slave
109 
110     oneWireUdelay(J); // Complete the reset sequence recovery
111 
112     result2 = oneWireGpioGet(gpio_device) ^ 0x01; // Sample for presence pulse from slave
113 
114     amp_warn(MOD_STR, "oneWireTouchReset[%d] result1 = %d, result2 = %d", __LINE__, result1, result2);
115 
116     return !((result1 == 1) && (result2 == 0)); // Return sample presence pulse result
117 }
118 
119 //-----------------------------------------------------------------------------
120 // Send a 1-Wire write bit. Provide 10us recovery time.
121 //
OneWireWriteBit(gpio_dev_t * gpio_device,int bit)122 void OneWireWriteBit(gpio_dev_t *gpio_device, int bit)
123 {
124     //amp_warn(MOD_STR, "OneWireWriteBit[%d] bit = %d", __LINE__, bit);
125 
126     if (bit)
127     {
128             // Write '1' bit
129             oneWireGpioSet(gpio_device, 0x00); // Drives DQ low
130 
131             oneWireUdelay(1);
132 
133             oneWireGpioSet(gpio_device, 0x01); // Releases the bus
134 
135             oneWireUdelay(30); // Complete the time slot and 10us recovery
136     }
137     else
138     {
139             // Write '0' bit
140             oneWireGpioSet(gpio_device, 0x00); // Drives DQ low
141 
142             oneWireUdelay(30);
143 
144             oneWireGpioSet(gpio_device, 0x01); // Releases the bus
145 
146             oneWireUdelay(1);
147     }
148 }
149 
150 //-----------------------------------------------------------------------------
151 // Read a bit from the 1-Wire bus and return it. Provide 10us recovery time.
152 //
OneWireReadBit(gpio_dev_t * gpio_device)153 int OneWireReadBit(gpio_dev_t *gpio_device)
154 {
155         int result;
156 
157         oneWireGpioSet(gpio_device, 0x00); // Drives DQ low
158 
159         oneWireUdelay(1);
160 
161         oneWireGpioSet(gpio_device, 0x01); // Releases the bus
162 
163         oneWireUdelay(2);
164 
165         result = oneWireGpioGet(gpio_device) & 0x01; // Sample the bit value from the slave
166 
167         oneWireUdelay(40); // Complete the time slot and 10us recovery
168 
169         //amp_warn(MOD_STR, "OneWireReadBit[%d] result = %d", __LINE__, result);
170 
171         return result;
172 }
173 
174 //-----------------------------------------------------------------------------
175 // Write 1-Wire data byte
176 //
OneWireWriteByte(gpio_dev_t * gpio_device,int data)177 void OneWireWriteByte(gpio_dev_t *gpio_device, int data)
178 {
179         int loop;
180 
181         // Loop to write each bit in the byte, LS-bit first
182         for (loop = 0; loop < 8; loop++)
183         {
184                 OneWireWriteBit(gpio_device, data & 0x01);
185 
186                 // shift the data byte for the next bit
187                 data >>= 1;
188         }
189 }
190 
191 //-----------------------------------------------------------------------------
192 // Read 1-Wire data byte and return it
193 //
OneWireReadByte(gpio_dev_t * gpio_device)194 int OneWireReadByte(gpio_dev_t *gpio_device)
195 {
196     int loop, result=0;
197 
198     for (loop = 0; loop < 8; loop++)
199     {
200             // shift the result to get it ready for the next bit
201             result >>= 1;
202 
203             // if result is one, then set MS bit
204             if (OneWireReadBit(gpio_device))
205             {
206                 result |= 0x80;
207             }
208 
209     }
210     //amp_warn(MOD_STR, "OneWireReadByte[%d] data = 0x%x", __LINE__, result);
211 
212     return result;
213 }
214 
delayus(unsigned int z)215 void delayus(unsigned int z)
216 {
217         while(z--);
218 }
219 //-----------------------------------------------------------------------------
220 // Set the 1-Wire timing to 'standard' (standard=1) or 'overdrive' (standard=0).
221 //
oneWireSetSpeed(int standard)222 void oneWireSetSpeed(int standard)
223 {
224     unsigned long now,t;
225 
226     // Adjust tick values depending on speed
227     if (standard)
228     {
229             // Standard Speed
230             // A = 6 * 4;
231             // B = 64 * 4;
232             // C = 60 * 4;
233             // D = 10 * 4;
234             // E = 9 * 4;
235             // F = 55 * 4;
236             // G = 0;
237             // H = 480 * 4;
238             // I = 70 * 4;
239             // J = 410 * 4;
240 
241             A = 6;
242             B = 64;
243             C = 60;
244             D = 10;
245             E = 9;
246             F = 55;
247             G = 0;
248             H = 480;
249             I = 70;
250             J = 410;
251     }
252     else
253     {
254             // Overdrive Speed
255             A = 1.5 * 4;
256             B = 7.5 * 4;
257             C = 7.5 * 4;
258             D = 2.5 * 4;
259             E = 0.75 * 4;
260             F = 7 * 4;
261             G = 2.5 * 4;
262             H = 70 * 4;
263             I = 8.5 * 4;
264             J = 40 * 4;
265     }
266 
267     now = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
268     oneWireUdelay(A);
269     t = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
270     amp_warn(MOD_STR, "[%d]hal_cmu_get_crystal_freq[%d] delta = %d", A, hal_cmu_get_crystal_freq(), (t-now));
271 
272     now = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
273     oneWireUdelay(B);
274     t = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
275     amp_warn(MOD_STR, "[%d]hal_cmu_get_crystal_freq[%d] delta = %d", B, hal_cmu_get_crystal_freq(), (t-now));
276 
277     now = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
278     oneWireUdelay(C);
279     t = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
280     amp_warn(MOD_STR, "[%d]hal_cmu_get_crystal_freq[%d] delta = %d", C, hal_cmu_get_crystal_freq(), (t-now));
281 
282 
283     now = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
284     oneWireUdelay(D);
285     t = FAST_TICKS_TO_US(hal_fast_sys_timer_get());
286     amp_warn(MOD_STR, "[%d]hal_cmu_get_crystal_freq[%d] delta = %d", D, hal_cmu_get_crystal_freq(), (t-now));
287 
288 }
289 
290 //-----------------------------------------------------------------------------
291 // Set the 1-Wire timing to 'standard' (standard=1) or 'overdrive' (standard=0).
292 //
native_onewire_gpio_setspeed(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)293 static JSValue native_onewire_gpio_setspeed(JSContext *ctx, JSValueConst this_val,
294                           int argc, JSValueConst *argv)
295 {
296     int standard  = 0;
297     int8_t result = -1;
298 
299     if((argc < 1) || (0 != JS_ToInt32(ctx, &standard, argv[0])))
300     {
301         amp_warn(MOD_STR, "parameter is invalid\n");
302         goto out;
303     }
304     printf("[%s][%d]standard = %d\n\r", __FUNCTION__, __LINE__, standard);
305     //oneWireSetSpeed(standard);
306     result = 0;
307 out:
308     return JS_NewInt32(ctx, result);
309 }
310 
native_onewire_gpio_open(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)311 static JSValue native_onewire_gpio_open(JSContext *ctx, JSValueConst this_val,
312                           int argc, JSValueConst *argv)
313 {
314     int8_t ret = -1;
315 
316     item_handle_t gpio_handle;
317     gpio_handle.handle      = NULL;
318     gpio_dev_t *gpio_device = NULL;
319     const char *id;
320 
321     if((argc < 1) || (!JS_IsString(argv[0])))
322     {
323         amp_warn(MOD_STR, "parameter is invalid, argc = %d\n", argc);
324         goto out;
325     }
326 
327     id = JS_ToCString(ctx, argv[0]);
328 
329     ret = board_attach_item(MODULE_GPIO, id, &gpio_handle);
330     if (0 != ret) {
331         amp_error(MOD_STR, "board_attach_item fail!, id %s", id);
332         goto out;
333     }
334     amp_debug(MOD_STR, "gpio handle:%p\n", gpio_handle.handle);
335     gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
336     if (NULL == gpio_device) {
337         amp_error(MOD_STR, "board_get_node_by_handle fail!");
338         goto out;
339     }
340 
341     ret = aos_hal_gpio_init(gpio_device);
342     if (0 != ret) {
343         amp_error(MOD_STR, "aos_hal_gpio_init fail!");
344         goto out;
345     }
346     // gpio_device->priv = NULL;
347     gpio_init_flag |= (1 << gpio_device->port);
348 
349     amp_error(MOD_STR, "aos_hal_gpio_init ret = %d!", ret);
350 out:
351     if (id != NULL) {
352         JS_FreeCString(ctx, id);
353     }
354     if (0 != ret) {
355         JS_SetContextOpaque(ctx, NULL);
356         board_disattach_item(MODULE_GPIO, &gpio_handle);
357     } else {
358         JSValue obj;
359         obj = JS_NewObjectClass(ctx, js_onewire_class_id);
360         JS_SetOpaque(obj, (void *)gpio_handle.handle);
361         return obj;
362     }
363     return JS_NewInt32(ctx, 0);
364 }
365 
native_onewire_gpio_close(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)366 static JSValue native_onewire_gpio_close(JSContext *ctx, JSValueConst this_val,
367                           int argc, JSValueConst *argv)
368 {
369     int32_t ret = -1;
370     item_handle_t gpio_handle;
371     gpio_dev_t *gpio_device = NULL;
372 
373     gpio_handle.handle = JS_GetOpaque2(ctx, this_val, js_onewire_class_id);
374     if (!gpio_handle.handle) {
375         amp_warn(MOD_STR, "parameter must be handle");
376         goto out;
377     }
378 
379     gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
380     if (NULL == gpio_device) {
381         amp_error(MOD_STR, "board_get_node_by_handle fail!");
382         goto out;
383     }
384     ret = aos_hal_gpio_finalize(gpio_device);
385     if (0 != ret) {
386         amp_error(MOD_STR, "aos_hal_gpio_finalize fail!");
387         goto out;
388     }
389     board_disattach_item(MODULE_GPIO, &gpio_handle);
390 
391 out:
392     return JS_NewInt32(ctx, ret);
393 }
394 
native_onewire_gpio_reset(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)395 static JSValue native_onewire_gpio_reset(JSContext *ctx, JSValueConst this_val,
396                           int argc, JSValueConst *argv)
397 {
398     item_handle_t gpio_handle;
399     int result = -1;
400     gpio_dev_t *gpio_device = NULL;
401 
402     gpio_handle.handle = JS_GetOpaque2(ctx, this_val, js_onewire_class_id);
403     if (!gpio_handle.handle) {
404         amp_warn(MOD_STR, "parameter must be handle");
405         goto out;
406     }
407 
408     gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
409     if (NULL == gpio_device) {
410         amp_error(MOD_STR, "board_get_node_by_handle fail!");
411         goto out;
412     }
413 
414     //result = oneWireTouchReset(gpio_device);
415     result = 0;
416 
417 out:
418     return JS_NewInt32(ctx, result);
419 }
420 
native_onewire_gpio_readbyte(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)421 static JSValue native_onewire_gpio_readbyte(JSContext *ctx, JSValueConst this_val,
422                           int argc, JSValueConst *argv)
423 {
424     item_handle_t gpio_handle;
425     int result;
426     gpio_dev_t *gpio_device = NULL;
427 
428     gpio_handle.handle = JS_GetOpaque2(ctx, this_val, js_onewire_class_id);
429     if (!gpio_handle.handle) {
430         amp_warn(MOD_STR, "parameter must be handle");
431         goto out;
432     }
433 
434     gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
435     if (NULL == gpio_device) {
436         amp_error(MOD_STR, "board_get_node_by_handle fail!");
437         goto out;
438     }
439 
440     //result = OneWireReadByte(gpio_device);
441     result = 0;
442 
443 out:
444     return JS_NewInt32(ctx, result);
445 }
446 
native_onewire_gpio_writebyte(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)447 static JSValue native_onewire_gpio_writebyte(JSContext *ctx, JSValueConst this_val,
448                           int argc, JSValueConst *argv)
449 {
450     item_handle_t gpio_handle;
451     int result = 0;
452     gpio_dev_t *gpio_device = NULL;
453     int32_t level  = 0;
454 
455     if((argc < 1) || (0 != JS_ToInt32(ctx, &level, argv[0])))
456     {
457         amp_warn(MOD_STR, "parameter is invalid\n");
458         goto out;
459     }
460 
461     gpio_handle.handle = JS_GetOpaque2(ctx, this_val, js_onewire_class_id);
462     if (!gpio_handle.handle) {
463         amp_warn(MOD_STR, "parameter must be handle");
464         goto out;
465     }
466 
467     gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
468 
469     if (NULL == gpio_device) {
470         amp_error(MOD_STR, "board_get_node_by_handle fail!");
471         goto out;
472     }
473 
474     //OneWireWriteByte(gpio_device, level);
475 
476     result = 1;
477 
478 out:
479     return JS_NewInt32(ctx, result);
480 }
481 
482 static JSClassDef js_onewire_class = {
483     "ONEWIRE",
484 };
485 
486 static const JSCFunctionListEntry js_onewire_funcs[] = {
487     JS_CFUNC_DEF("open", 1, native_onewire_gpio_open ),
488     JS_CFUNC_DEF("setspeed", 1, native_onewire_gpio_setspeed ),
489     JS_CFUNC_DEF("reset", 0, native_onewire_gpio_reset ),
490     JS_CFUNC_DEF("readByte", 0, native_onewire_gpio_readbyte),
491     JS_CFUNC_DEF("writeByte", 1, native_onewire_gpio_writebyte),
492     JS_CFUNC_DEF("close", 0, native_onewire_gpio_close),
493 };
494 
js_onewire_init(JSContext * ctx,JSModuleDef * m)495 static int js_onewire_init(JSContext *ctx, JSModuleDef *m)
496 {
497     JSValue proto;
498 
499     JS_NewClassID(&js_onewire_class_id);
500 
501     JS_NewClass(JS_GetRuntime(ctx), js_onewire_class_id, &js_onewire_class);
502     proto = JS_NewObject(ctx);
503     JS_SetPropertyFunctionList(ctx, proto, js_onewire_funcs,
504                                countof(js_onewire_funcs));
505     JS_SetClassProto(ctx, js_onewire_class_id, proto);
506 
507     return JS_SetModuleExportList(ctx, m, js_onewire_funcs,
508                                   countof(js_onewire_funcs));
509 }
510 
js_init_module_onewire(JSContext * ctx,const char * module_name)511 JSModuleDef *js_init_module_onewire(JSContext *ctx, const char *module_name)
512 {
513     JSModuleDef *m;
514     m = JS_NewCModule(ctx, module_name, js_onewire_init);
515     if (!m)
516         return NULL;
517     JS_AddModuleExportList(ctx, m, js_onewire_funcs, countof(js_onewire_funcs));
518     return m;
519 }
520 
module_onewire_register(void)521 void module_onewire_register(void)
522 {
523     amp_debug(MOD_STR, "module_onewire_register");
524     JSContext *ctx = js_get_context();
525     aos_printf("module onewire register\n");
526     js_init_module_onewire(ctx, "ONEWIRE");
527 }
528