ממשק ה-HAL של חיישנים, שמוצהר ב-sensors.h, מייצג את הממשק בין המסגרת של Android לבין התוכנה הספציפית לחומרה. חובה להגדיר כל פונקציה של הטמעת HAL שהוצהר בחיישנים. הפונקציות העיקריות הן:
get_sensors_list
– הפונקציה מחזירה רשימה של כל החיישנים.activate
– הפעלה או עצירה של החיישן.batch
– הגדרת הפרמטרים של החיישן, כמו תדירות דגימה ומקסימום זמן אחזור של הדיווח.setDelay
– בשימוש רק בגרסה 1.0 של HAL. מגדיר את תדירות הדגימה של לחיישן מסוים.flush
- שנקה את ערך ה-FIFO של החיישן שצוין ודיווח על השלמת שטיפה לאחר ביצוע הפעולה הזו.poll
– הפונקציה מחזירה את אירועי החיישן הזמינים.
ההטמעה חייבת להיות בטוחה לשרשור ולאפשר להפעיל את הפונקציות האלה משרשוריים שונים.
הממשק מגדיר גם כמה סוגים שבהם נעשה שימוש בפונקציות האלה. הסוגים העיקריים הם:
sensors_module_t
sensors_poll_device_t
sensor_t
sensors_event_t
בנוסף לקטעים הבאים, מידע נוסף על הסוגים האלה זמין בקובץ sensors.h.
get_sensors_list(list)
int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list);
רשימת החיישנים שהוטמעו על ידי HAL. מידע על הגדרות החיישנים זמין בכתובת sensor_t.
הסדר שבו החיישנים מופיעים ברשימה הוא הסדר שבו החיישנים ידווחו לאפליקציות. בדרך כלל החיישנים הבסיסיים מופיעים קודם, ואחריהם החיישנים המשולבים.
אם כמה חיישנים משתפים את אותו סוג חיישן ואת אותו מאפיין התעוררות, החיישן הראשון ברשימה נקרא 'חיישן ברירת המחדל'. זהו הערך שמוחזר על ידי getDefaultSensor(int sensorType, bool wakeUp)
.
הפונקציה הזו מחזירה את מספר החיישנים ברשימה.
activate(sensor, true/false)
int (*activate)(struct sensors_poll_device_t *dev, int sensor_handle, int enabled);
המתג מפעיל או משבית את החיישן.
sensor_handle
היא נקודת האחיזה של החיישן להפעלה/השבתה. הידית של חיישן מוגדרת לפי השדה handle
במבנה sensor_t שלו.
כדי להפעיל את החיישן, מגדירים את enabled
כ-1. כדי להשבית אותו, מגדירים אותו כ-0.
חיישנים מסוג 'ירייה אחת' משביתים את עצמם באופן אוטומטי לאחר קבלת אירוע, אבל עדיין צריך לאשר את השבתתם באמצעות קריאה ל-activate(...,
enabled=0)
.
חיישנים שאי אפשר להוציא ממצב שינה אף פעם לא מונעים מה-SoC לעבור למצב השעיה. ש היא, HAL לא יוכל להחזיק נעילה חלקית של מצב שינה מטעם האפליקציות.
חיישני התעוררות, כשהם שולחים אירועים באופן רציף, יכולים למנוע מה-SoC לעבור למצב השהיה, אבל אם אין צורך לשלוח אירוע, צריך לשחרר את נעילת ההתעוררות החלקית.
אם הערך של enabled
הוא 1 והחיישן כבר מופעל, הפונקציה הזו לא פועלת
ומצליחה.
אם הערך של enabled
הוא 0 והחיישן כבר מושבת, הפונקציה לא פועלת
ומצליחה.
הפונקציה מחזירה 0 אם הפעולה בוצעה בהצלחה, ומספר שגיאה שלילי אחרת.
אצווה(חיישן, דגלים, תקופת דגימה, זמן אחזור מקסימלי של דוח)
int (*batch)( struct sensors_poll_device_1* dev, int sensor_handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns);
מגדירה את הפרמטרים של החיישן, כולל תדירות הדגימה וגם מספר דוח מקסימלי זמן אחזור. ניתן לקרוא לפונקציה הזו בזמן שהחיישן מופעל, במקרה כזה, אסור שהמדידות של החיישן יאבדו: מתדירות דגימה אחת לשנייה לא יכולה לגרום לאובדן אירועים, וגם לא יכולה מעבר מזמן אחזור מקסימלי גבוה של דוח לדוח מקסימלי נמוך זמן אחזור.
sensor_handle
הוא נקודת האחיזה של החיישן שרוצים להגדיר.
flags
לא בשימוש כרגע.
sampling_period_ns
הוא תקופת הדגימה שבה החיישן
אמור לפעול תוך ננו-שניות. ראו sampling_period_ns
פרטים נוספים.
max_report_latency_ns
הוא משך הזמן המקסימלי שבו אירועים יכולים להיות
עיכוב לפני דיווח באמצעות HAL, בננו-שניות. הצגת max_report_latency_ns
לפרטים נוספים.
הפונקציה מחזירה 0 אם הפעולה בוצעה בהצלחה, ומספר שגיאה שלילי אחרת.
setDelay(חיישן, תקופת דגימה)
int (*setDelay)( struct sensors_poll_device_t *dev, int sensor_handle, int64_t sampling_period_ns);
אחרי גרסה 1.0 של HAL, הפונקציה הזו יצאה משימוש ואף פעם לא מתבצעת קריאה שלה.
במקום זאת, הפונקציה batch
נקראת כדי להגדיר את הפרמטר sampling_period_ns
.
בגרסה 1.0 של HAL נעשה שימוש ב-setDelay במקום באצווה כדי להגדיר את sampling_period_ns.
Flush(sensor)
int (*flush)(struct sensors_poll_device_1* dev, int sensor_handle);
מוסיפים אירוע של סיום שטיפה לסוף ה-FIFO של החומרה עבור החיישן שצוין ומנקים את ה-FIFO. האירועים האלה נשלחים כרגיל (כלומר, כאילו פג תוקף זמן האחזור המקסימלי לדיווח) ומוסרים מה-FIFO.
הניקוי מתבצע באופן אסינכרוני (כלומר, הפונקציה הזו חייבת לחזור מיד). אם בהטמעה נעשה שימוש ב-FIFO אחד לכמה חיישנים, ה-FIFO ואירוע 'הניקוי' יתווסף רק לחיישן שצוין.
אם לחיישן שצוין אין FIFO (לא ניתן להשתמש במאגר), או אם ה-FIFO היה ריק בזמן הקריאה, flush
עדיין צריך להצליח ולשלוח אירוע של סיום שטיפה לחיישן הזה. הכלל הזה חל על כל החיישנים האחרים
מחיישנים במודל אחד.
כשפונים ל-flush
, גם אם אירוע שטיפה כבר נמצא ב-FIFO של החיישן הזה, צריך ליצור אירוע נוסף ולהוסיף אותו לסוף ה-FIFO, וגם צריך לבצע שטיפה של ה-FIFO. מספר הflush
הקריאות חייבות להיות שווה למספר האירועים מסוג 'רצף רצף' שנוצרו.
flush
לא רלוונטי לחיישנים מסוג one-shot. אם sensor_handle
מתייחס לחיישן מסוג one-shot, flush
חייב להחזיר את הערך -EINVAL
ולא ליצור אירוע של שטיפה מלאה של המטא-נתונים.
הפונקציה הזו מחזירה 0 אם הפעולה בוצעה בהצלחה, -EINVAL
אם החיישן שצוין הוא חיישן חד-פעמי או לא הופעל, ומספר שגיאה שלילי במקרים אחרים.
poll()
int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int
count);
מחזירה מערך של נתוני חיישנים על ידי מילוי הארגומנט data
. הפונקציה הזו חייבת לחסום עד שהאירועים יהיו זמינים. הפעולה הזו תחזיר את מספר האירועים שנקראו
או מספר שגיאה שלילי במקרה של שגיאה.
מספר האירועים שהוחזרו ב-data
חייב להיות שווה ל- או קטן מ-
את הארגומנט count
. הפונקציה הזו אף פעם לא תחזיר 0 (אין אירוע).
רצף שיחות
כשהמכשיר מופעל, מתבצעת קריאה ל-get_sensors_list
.
כשהחיישן מופעל, תתבצע קריאה לפונקציה batch
באמצעות
הפרמטרים המבוקשים, ואחריהם activate(..., enable=1)
.
שימו לב שבגרסה 1_0 של HAL, הסדר היה הפוך: activate
הופעל קודם, ואחריו set_delay
.
כשהמאפיינים המבוקשים של חיישן משתנים בזמן שהוא מופעל, מתבצעת קריאה לפונקציה batch
.
אפשר להתקשר אל flush
בכל שלב, גם באמצעות חיישנים לא פעילים (במקרה כזה)
היא חייבת להחזיר -EINVAL
)
כשחיישן מושבת, מתבצעת קריאה ל-activate(..., enable=0)
.
במקביל לקריאות האלה, הפונקציה poll
תופעל שוב ושוב כדי לבקש נתונים. אפשר להתקשר אל poll
גם אם לא הופעלו חיישנים.
חיישנים_Module_t
sensors_module_t
הוא הסוג שמשמש ליצירת מודול החומרה של Android לחיישנים. כשמטמיעים את ה-HAL, חייבים להגדיר אובייקט
HAL_MODULE_INFO_SYM
מהסוג הזה כדי לחשוף את הפונקציה get_sensors_list. לצפייה
הגדרה של sensors_module_t
ב-sensors.h וההגדרה של hw_module_t
אפשר לקבל מידע נוסף.
sensors_poll_device_t / sensors_poll_device_1_t
sensors_poll_device_1_t
מכיל את שאר השיטות שהוגדרו למעלה:
activate
, batch
, flush
וגם
poll
. שדה common
שלו (מסוג hw_device_t)
מגדיר את מספר הגרסה של HAL.
חיישן_t
sensor_t
מייצג Android
חיישן. הנה כמה מהשדות החשובים בו:
name: מחרוזת שגלויה למשתמש ומייצגת את החיישן. המחרוזת הזו מכילה לרוב את שם החלק של החיישן הבסיסי, את סוג החיישן ואת העובדה שהוא חיישן התעוררות. לדוגמה, 'LIS2HH12 Accelerometer', 'MAX21000 Uncalibrated Gyroscope', 'BMP280 Wake-up Barometer', 'MPU6515 Game Rotation Vector'
handle: המספר השלם שמשמש להפניה לחיישן כשרוצים להירשם אליו או ליצור ממנו אירועים.
type: סוג החיישן. הצגת הסבר על החיישן
מקלידים מהם חיישני Android? לקבלת פרטים נוספים, וקוראים את המאמר סוגי חיישנים עבור סוגי חיישנים רשמיים. עבור
סוגי חיישנים לא רשמיים, type
חייב להתחיל ב-SENSOR_TYPE_DEVICE_PRIVATE_BASE
stringType: סוג החיישן כמחרוזת. אם לסוג החיישן יש סוג רשמי, מגדירים אותו כ-SENSOR_STRING_TYPE_*
. כשלחיישן יש סוג ספציפי ליצרן, השדה stringType
חייב להתחיל בשם הדומיין ההפוך של היצרן. לדוגמה, חיישן
מזהה חד-קרן) שהוגדר על ידי צוות מוצר מגניב
חברה בדיונית יכולה להשתמש
stringType=”com.fictional_company.cool_product.unicorn_detector”
.
stringType
משמש לזיהוי ייחודי של חיישנים לא רשמיים
שונים. למידע נוסף על סוגי מחרוזות וסוגים אחרים, אפשר לעיין בקובץ sensors.h.
requiredPermission: מחרוזת שמייצגת את ההרשאה שצריכה להיות לאפליקציות כדי לראות את החיישן, להירשם אליו ולקבל את הנתונים שלו. אם מופיעה מחרוזת ריקה, פירוש הדבר הוא שאפליקציות לא דורשות הרשאות כדי
לגשת לחיישן הזה. לחלק מסוגי החיישנים, כמו מוניטור קצב הלב, יש
חובה requiredPermission
. כל החיישנים מספקים מידע רגיש
על נתוני המשתמש (כמו דופק)
הרשאה.
דגלים: סימונים עבור חיישן זה, המגדירים את מצב הדיווח של החיישן
החיישן הוא חיישן התעוררות או לא. לדוגמה: חיישן התעוררות בפעולה אחת
יהיה flags = SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP
. הקטעים של
הדגל שלא נעשה בו שימוש בגרסת ה-HAL הנוכחית חייב להיות שווה ל-0.
maxRange: הערך המקסימלי שהחיישן יכול לדווח, באותה יחידה שבה מדווחים הערכים. החיישן יכול לדווח על ערכים בלי רוויה
בתוך [-maxRange; maxRange]
. חשוב לשים לב שהמשמעות היא שהטווח הכולל של
במשמעות הגנרית, 2*maxRange
. כשהחיישן מדווח על ערכים מעל
כמה צירים, הטווח חל על כל ציר. לדוגמה, מד תאוצה עם טווח של +/- 2g ידווח על maxRange = 2*9.81 = 2g
.
רזולוציה: ההבדל הקטן ביותר בערך שהחיישן יכול למדוד.
בדרך כלל מחושב על סמך maxRange
ומספר הביטים במדידה.
הספק: עלות החשמל של הפעלת החיישן, באלפיות השנייה.
המדד הזה כמעט תמיד גבוה מצריכת החשמל שדווחה
של החיישן הבסיסי. ראו חיישני בסיס != פיזי
חיישנים לפרטים נוספים ולמידע על מדידת עוצמה
תהליך לפרטים על האופן שבו ניתן למדוד את צריכת החשמל של חיישן.
אם צריכת החשמל של החיישן תלויה בתנועה של המכשיר, צריכת החשמל בזמן התנועה היא זו שמדווחת בשדה power
.
minDelay: בחיישנים רציפים, תקופת הדגימה
מיקרו-שניות, בהתאם לקצב המהיר ביותר שנתמך בחיישן. ראו sampling_period_ns
פרטים על אופן השימוש בערך הזה. חשוב לזכור ש-minDelay
מופיע ביחידות מיקרו-שנייה, ואילו sampling_period_ns
מופיע ביחידות ננו-שנייה. בחיישנים של דיווח בזמן שינוי ובדיווח מיוחד, אלא אם צוין אחרת, הערך של minDelay
חייב להיות 0. לחיישנים במבט אחד,
חייב להיות 1-.
maxDelay: בחיישנים רצויים בחיישנים שמנטרים שינויים, תקופת הדגימה, במיקרו-שניות, בהתאם לשיעור האיטי ביותר שהחיישן תומך בו. ראו sampling_period_ns
פרטים על אופן השימוש בערך הזה. חשוב לזכור ש-maxDelay
מופיע ביחידות מיקרו-שנייה, ואילו sampling_period_ns
מופיע ביחידות ננו-שנייה. לחיישנים מיוחדים ולחיישנים חד-פעמיים, maxDelay
חייב להיות
0.
fifoReserveEventCount: מספר האירועים ששמורים לחיישן הזה
FIFO לחומרה. אם יש FIFO ייעודי לחיישן הזה,
fifoReservedEventCount
הוא הגודל של ה-FIFO הייעודי הזה. אם ה-FIFO הוא
משותף עם חיישנים אחרים, fifoReservedEventCount
הוא הגודל של החלק
ה-FIFO ששמור לאותו חיישן. ברוב מערכות FIFO המשותפות, ובמצב
למערכות שאין להן FIFO לחומרה, הערך הזה הוא 0.
fifoMaxEventCount: המספר המקסימלי של אירועים שיכולים
להיות מאוחסנים ביחידות ה-FIFO של החיישן הזה. הערך הזה תמיד גדול מ-fifoReservedEventCount
או שווה לו. הערך הזה משמש להערכה של האופן שבו
מהירות ה-FIFO תתמלא במהירות במהלך הרישום לחיישן
בתנאי שלא הופעלו חיישנים אחרים. במערכות שאין להן
FIFO של החומרה, fifoMaxEventCount
הוא 0. לפרטים נוספים, ראו אצווה.
בחיישני סוג רשמי, חלק מהשדות נכתבים מחדש על ידי המסגרת. לדוגמה, חיישנים של מד תאוצה חייבים לפעול במצב דיווח רציף, ומוניטורים של קצב הלב חייבים להיות מוגנים באמצעות ההרשאה SENSOR_PERMISSION_BODY_SENSORS
.
sensors_event_t
אירועי חיישנים שנוצרים על ידי חיישני Android ומדווחים באמצעות פונקציית הסקר הם מתוך type sensors_event_t
. הנה כמה דוגמאות
שדות חשובים ב-sensors_event_t
:
גרסה: חייבת להיות sizeof(struct sensors_event_t)
sensor: נקודת האחיזה של החיישן שיצר את האירוע, לפי ההגדרה של
sensor_t.handle
.
type: סוג החיישן של החיישן שיצר את האירוע, כפי שמוגדר על ידי sensor_t.type
.
timestamp: חותמת הזמן של האירוע בננו-שניות. זו השעה שבה
התרחש אירוע (בוצע שלב, או שבוצעה מדידה של מד תאוצה),
לא השעה שבה דווח על האירוע. חובה לסנכרן את timestamp
עם
בשעון elapsedRealtimeNano
, ובמקרה של חיישנים רציפים, הרעידות
חייב להיות קטן. לפעמים צריך לסנן את חותמות הזמן כדי לעמוד בדרישות של CDD, כי שימוש רק בזמן ההפרעה של SoC כדי להגדיר את חותמות הזמן גורם לתנודות גבוהות מדי, ושימוש רק בזמן של צ'יפ החיישן כדי להגדיר את חותמות הזמן עלול לגרום לניתוק הסנכרון עם השעון elapsedRealtimeNano
, כי שעון החיישן נע.
data ושדות חופפים: הערכים שנמדדים באמצעות
באמצעות חיישן. המשמעות והיחידות של השדות האלה ספציפיות לכל סוג חיישן. לתיאור של סוגי החיישנים השונים, אפשר לעיין בקטע sensors.h
שדות נתונים. עבור חיישנים מסוימים, יש דיווח גם על רמת הדיוק של התוצאות
כחלק מהנתונים, באמצעות שדה status
. בשדה הזה בלבד
של סוגי החיישנים שנבחרו, ומופיעים בשכבת ה-SDK
ערך הדיוק. לגבי החיישנים האלה, העובדה שצריך להגדיר את שדה הסטטוס מופיעה בהגדרה של סוג החיישן.
אירועים שהושלמו של מטא-נתונים
הסוג של אירועי מטא-נתונים זהה לזה של אירועי חיישנים רגילים:
sensors_event_meta_data_t = sensors_event_t
הם מוחזרים יחד עם אירועים אחרים של חיישנים באמצעות סקרים. הם כוללים את השדות הבאים:
גרסה: חייבת להיות META_DATA_VERSION
type: חייב להיות SENSOR_TYPE_META_DATA
sensor, reserved ו-timestamp: חייבים להיות 0
meta_data.what: מכיל את סוג המטא-נתונים של האירוע הזה. כרגע יש
סוג מטא-נתונים חוקי אחד: META_DATA_FLUSH_COMPLETE
.
אירועי META_DATA_FLUSH_COMPLETE
מייצגים את השלמת תהליך השדרוג
החיישן FIFO. כשהערך הוא meta_data.what=META_DATA_FLUSH_COMPLETE
, meta_data.sensor
צריך להיות מוגדר לנקודת האחיזה של החיישן שהתרוקן. הם נוצרים רק כשמתבצעת קריאה ל-flush
באחד מהחיישנים. צפייה בקטע שעוסק ב-
את הפונקציה flush.