module main
author unknown
version 1 0 
description ''
variables '计数' '启动' 

	spec ' ' '前进' '前进 _' 'auto' '10'
	spec ' ' '右转' '右转 _' 'auto' '10'
	spec ' ' '右转到黑线2' '右转到黑线2'
	spec ' ' '右转巡到黑线' '右转巡到黑线'
	spec ' ' '后退' '后退 _' 'auto' '10'
	spec ' ' '巡线' '巡线'
	spec ' ' '巡线到0000' '巡线到0000'
	spec ' ' '巡线到0111' '巡线到0111'
	spec ' ' '巡线到1110' '巡线到1110'
	spec ' ' '巡线到1111' '巡线到1111'
	spec ' ' '左转' '左转 _' 'auto' '10'
	spec ' ' '左转到黑线2' '左转到黑线2'
	spec ' ' '左转巡到黑线' '左转巡到黑线'
	spec ' ' '手动' '手动'
	spec ' ' '显示心形' '显示心形'
	spec ' ' '电机停止' '电机停止 _' 'auto' '10'
	spec ' ' '直走巡到黑线' '直走巡到黑线'
	spec ' ' '阶段1' '阶段1'
	spec ' ' '阶段2' '阶段2'
	spec ' ' '阶段3' '阶段3'
	spec ' ' '颜色识别' '颜色识别'
	spec ' ' '选充能区' '选充能区'
	spec ' ' '计时巡线' '计时巡线 _' 'auto' '10'
	spec ' ' '前舵机' '前舵机 _' 'auto' '10'
	spec ' ' '后舵机' '后舵机 _' 'auto' '10'
	spec ' ' '巡线到0000无前' '巡线到0000无前'

to '前舵机' foo {
  'stop all motors'
  'set servo angle' '360' 1 foo
  waitMillis 200
}

to '前进' foo {
  'set motor speed' 1 25
  'set motor speed' 2 25
  waitMillis foo
}

to '右转' foo {
  'set motor speed' 1 25
  'set motor speed' 2 -25
  waitMillis foo
}

to '右转到黑线2' {
  '右转' 300
  'Get a Trackbit state value'
  repeatUntil (and ('Trackbit channel' 2 '●') ('Trackbit channel' 3 '●')) {
    'Get a Trackbit state value'
  }
}

to '右转巡到黑线' {
  '右转' 300
  'Get a Trackbit state value'
  repeatUntil (or ('Trackbit channel' 2 '●') ('Trackbit channel' 3 '●')) {
    'Get a Trackbit state value'
  }
}

to '后舵机' foo {
  'stop all motors'
  'set servo angle' '360' 2 foo
  waitMillis 200
}

to '后退' foo {
  'set motor speed' 1 -25
  'set motor speed' 2 -25
  waitMillis foo
}

to '巡线' {
  'Get a Trackbit state value'
  if ('Trackbit is' '◌' '●' '●' '◌') {
    'set motor speed' 1 50
    'set motor speed' 2 50
  }
  if (or ('Trackbit is' '◌' '●' '◌' '◌') ('Trackbit is' '●' '●' '◌' '◌')) {
    'set motor speed' 1 10
    'set motor speed' 2 100
  }
  if (or ('Trackbit is' '◌' '◌' '●' '◌') ('Trackbit is' '◌' '◌' '●' '●')) {
    'set motor speed' 1 100
    'set motor speed' 2 10
  }
  if ('Trackbit is' '●' '◌' '◌' '◌') {
    'set motor speed' 1 5
    'set motor speed' 2 100
  }
  if ('Trackbit is' '◌' '◌' '◌' '●') {
    'set motor speed' 1 100
    'set motor speed' 2 5
  }
}

to '巡线到0000' {
  'Get a Trackbit state value'
  repeatUntil ('Trackbit is' '◌' '◌' '◌' '◌') {
    'Get a Trackbit state value'
    '巡线'
  }
  '前进' 250
}

to '巡线到0000无前' {
  'Get a Trackbit state value'
  repeatUntil ('Trackbit is' '◌' '◌' '◌' '◌') {
    'Get a Trackbit state value'
    '巡线'
  }
}

to '巡线到0111' {
  'Get a Trackbit state value'
  repeatUntil ('Trackbit is' '◌' '●' '●' '●') {
    '巡线'
  }
  '前进' 250
}

to '巡线到1110' {
  'Get a Trackbit state value'
  repeatUntil ('Trackbit is' '●' '●' '●' '◌') {
    '巡线'
  }
  '前进' 250
}

to '巡线到1111' {
  'Get a Trackbit state value'
  repeatUntil ('Trackbit is' '●' '●' '●' '●') {
    '巡线'
  }
  '前进' 250
}

to '左转' foo {
  'set motor speed' 1 -25
  'set motor speed' 2 25
  waitMillis foo
}

to '左转到黑线2' {
  '左转' 300
  'Get a Trackbit state value'
  repeatUntil (and ('Trackbit channel' 2 '●') ('Trackbit channel' 3 '●')) {
    'Get a Trackbit state value'
  }
}

to '左转巡到黑线' {
  '左转' 300
  'Get a Trackbit state value'
  repeatUntil (or ('Trackbit channel' 2 '●') ('Trackbit channel' 3 '●')) {
    'Get a Trackbit state value'
  }
}

to '手动' {
  forever {
    if ('[radio:messageReceived]') {
      if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 5)) {'前进' ''}
      if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 6)) {'后退' ''}
      if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 7)) {'左转' ''}
      if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 8)) {'右转' ''}
      if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 9)) {'set servo angle' '360' 1 132}
      if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 10)) {'set servo angle' '360' 1 0}
      if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 11)) {'stop all motors'}
    }
  }
}

to '显示心形' {
  '[display:mbDisplay]' 4685802
}

to '电机停止' foo {
  'stop all motors'
  waitMillis foo
}

to '直走巡到黑线' {
  '前进' ''
  'Get a Trackbit state value'
  repeatUntil (or ('Trackbit channel' 2 '●') ('Trackbit channel' 3 '●')) {
    'Get a Trackbit state value'
  }
}

to '计时巡线' 毫秒 {
  resetTimer
  repeatUntil (毫秒 < (timer)) {
    '巡线'
  }
}

to '选充能区' {
  repeatUntil ('[radio:messageReceived]') nil
  if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 1)) {
    '前进' 500
    '右转' 600
    '前进' 500
    '显示心形'
  }
  if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 2)) {
    '后退' 600
    '右转' 600
    '前进' 500
    '显示心形'
  }
  if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 3)) {
    '前进' 500
    '左转' 600
    '前进' 500
    '显示心形'
  }
  if (and (('[radio:receivedString]') == 'YLJY') (('[radio:receivedInteger]') == 4)) {
    '后退' 600
    '左转' 600
    '前进' 500
    '显示心形'
  }
}

to '阶段1' {
  'set servo angle' '360' 1 135
  'set servo angle' '360' 2 45
  '前进' 350
  '巡线到1111'
  '前舵机' 55
  '左转巡到黑线'
  '前进' 400
  '电机停止' 200
  '后退' 280
  '左转' 400
  '前进' 200
  '电机停止' 200
  '前舵机' 135
  '后退' 135
  '后退' 240
  '右转' 400
  '右转巡到黑线'
  '巡线到0000'
  '前进' 200
  '巡线到1110'
  '左转巡到黑线'
  '巡线到1111'
  '左转巡到黑线'
  '巡线到0111'
  '右转巡到黑线'
  '巡线到1110'
  '后舵机' 90
  '后退' 380
  '后舵机' 70
  waitMillis 200
  '后舵机' 90
  '巡线到0000无前'
  '前进' 80
  '后舵机' 70
}

to '阶段2' {
  'set servo angle' '360' 1 135
  'set servo angle' '360' 2 45
  '前进' 350
  '巡线到0111'
  '前舵机' 55
  '左转' 650
  '前进' 450
  '电机停止' 200
  '后退' 200
  '前舵机' 135
  '电机停止' 200
  '后退' 250
  '右转巡到黑线'
  '巡线到1111'
  '前舵机' 49
  '右转巡到黑线'
  '巡线到0000'
  '前舵机' 90
  '后退' 600
  '左转巡到黑线'
  '巡线到1111'
  '前舵机' 70
  '左转巡到黑线'
  '巡线到0000'
  '后退' 600
  '右转巡到黑线'
  '右转' 200
  '右转巡到黑线'
  '巡线到0000'
  '后退' 200
  '右转' 300
  '前舵机' 57
  '电机停止' 200
  '左转' 500
  '电机停止' 200
  '前舵机' 135
  '后退' 400
  '左转巡到黑线'
  '巡线到1111'
  '选充能区'
  'stop all motors'
}

to '阶段3' {
  'set servo angle' '360' 1 135
  'set servo angle' '360' 2 45
  '前进' 350
  '巡线到1111'
  '左转巡到黑线'
  '后退' 300
  '电机停止' 300
  '颜色识别'
}

to '颜色识别' {
  if (('get color') == 'red') {
    'set led' 'J1' true 100
    displayCharacter 'R'
    waitMillis 500
    '[display:mbDisplayOff]'
    'set led' 'J1' false 0
  }
  if (('get color') == 'yellow') {
    'set led' 'J2' true 100
    displayCharacter 'Y'
    waitMillis 500
    '[display:mbDisplayOff]'
    'set led' 'J2' false 0
  }
  if (('get color') == 'green') {
    'set led' 'J3' true 100
    displayCharacter 'G'
    waitMillis 500
    '[display:mbDisplayOff]'
    'set led' 'J3' false 0
  }
}

script 45 45 {
whenButtonPressed 'B'
启动 = (booleanConstant true)
if (计数 == 0) {
  displayCharacter '0'
  'stop all motors'
}
if (计数 == 1) {
  displayCharacter '1'
  '阶段1'
}
if (计数 == 2) {
  displayCharacter '2'
  '阶段2'
}
if (计数 == 3) {
  displayCharacter '3'
  '阶段3'
}
if (计数 == 4) {
  displayCharacter '4'
  '手动'
}
}

script 218 45 {
whenButtonPressed 'A'
计数 += 1
if (计数 > 4) {
  计数 = 0
}
if (计数 == 1) {
  displayCharacter '1'
}
if (计数 == 2) {
  displayCharacter '2'
}
if (计数 == 3) {
  displayCharacter '3'
}
if (计数 == 4) {
  displayCharacter '4'
}
}

script 378 45 {
whenStarted
'[display:mbDisplayOff]'
'[radio:setGroup]' 0
comment '广播分组听从比赛现场安排而设定'
计数 = 0
displayCharacter 计数
启动 = (booleanConstant false)
'stop all motors'
}


module AILens Input
author wwj718
version 1 0 
choices modeMenu Card Ball Color Face Tracking Learn 
description 'AI Lens

The AI Lens is able to achieve the functions of face recognition, balls tracking, cards recognition and characteristics acquisition.

ref: https://www.elecfreaks.com/learn-en/microbitplanetX/ai/Plant_X_EF05035.html
'
variables _Camera_Add _Card _Face _Ball _Tracking _Color _Learn _numberCards _letterCards _otherCards _colorList '_AILens initialized' _Data_buff _Temp_Data_buff _recursion_depth 

	spec ' ' '_AILens setup' '_AILens setup'
	spec ' ' '_get_image' '_get_image'
	spec ' ' 'switch_function' 'switch mode _' 'menu.modeMenu' 'Card'
	spec 'r' 'get_card_content' 'get_card_content'
	spec 'r' 'get_card_data' 'get_card_data'
	spec 'r' 'get_ball_color' 'get_ball_color'
	spec 'r' 'get_ball_data' 'get_ball_data'
	spec 'r' 'get_color_name' 'get_color_name'
	spec 'r' 'get_face' 'get_face'
	spec 'r' 'get_face_data' 'get_face_data'
	spec 'r' 'get_track_data' 'get_track_data'
	spec ' ' 'learn_object' 'learn_object _' 'menu.range:1-5' 1
	spec 'r' 'get_learn_data' 'get_learn_data'
	spec 'r' '_get_7_data' '_get_7_data'

to '_AILens setup' {
  if ((v '_AILens initialized') == 0) {
    _Camera_Add = (hexToInt '14')
    _Card = 0
    _Face = 0
    _Ball = 7
    _Tracking = 1
    _Color = 0
    _Learn = 0
    _numberCards = ('[data:makeList]' 0 1 2 3 4 5 6 7 8 9)
    _letterCards = ('[data:makeList]' 'A' 'B' 'C' 'D' 'E')
    _otherCards = ('[data:makeList]' 'Mouse' 'micro:bit' 'Ruler' 'Cat' 'Peer' 'Ship' 'Apple' 'Car' 'Pan' 'Dog' 'Umbrella' 'Airplane' 'Clock' 'Grape' 'Cup' 'Turn left' 'Turn right' 'Forward' 'Stop' 'Back')
    _colorList = ('[data:makeList]' 'Green' 'Blue' 'Yellow' 'Black' 'Red' 'White')
    _Temp_Data_buff = (newList 9)
    _Data_buff = (newList 9)
    _recursion_depth = 0
    local 'tmp' (newList 1)
    '[sensors:i2cRead]' _Camera_Add tmp
    '_AILens initialized' = 1
  }
}

to '_get_7_data' {
  '_get_image'
  comment 'return (a list):Data [x,y,w,h,confidence,total,order]'
  local 'data' ('[data:makeList]')
  for i 7 {
    '[data:addLast]' (at (i + 2) _Data_buff) data
  }
  return data
}

to '_get_image' {
  '_AILens setup'
  '[sensors:i2cRead]' _Camera_Add _Temp_Data_buff
  if (_Temp_Data_buff == _Data_buff) {
    waitMillis 100
    if (_recursion_depth < 5) {
      _recursion_depth = (_recursion_depth + 1)
      '_get_image'
    }
  } else {
    _Data_buff = _Temp_Data_buff
  }
}

to get_ball_color {
  '_get_image'
  if ((at 1 _Data_buff) == 7) {
    if ((at 2 _Data_buff) == 1) {
      return 'Blue'
    } else {
      if ((at 2 _Data_buff) == 2) {return 'Red'}
    }
  }
  if else {
    return '"No Ball"'
  }
}

to get_ball_data {
  return ('_get_7_data')
}

to get_card_content {
  '_get_image'
  if ((at 1 _Data_buff) == 2) {
    return (at (at 2 _Data_buff) _numberCards)
  }
  if ((at 1 _Data_buff) == 4) {
    return (at (at 2 _Data_buff) _letterCards)
  }
  if (and ((at 1 _Data_buff) == 3) ((at 2 _Data_buff) < 21)) {
    return (at (at 2 _Data_buff) _otherCards)
  }
  return 'No Card'
}

to get_card_data {
  return ('_get_7_data')
}

to get_color_name {
  '_get_image'
  if ((at 1 _Data_buff) == 9) {
    return (at (at 2 _Data_buff) _colorList)
  } else {
    return 'No Color'
  }
}

to get_face {
  '_get_image'
  return ((at 1 _Data_buff) == 6)
}

to get_face_data {
  return ('_get_7_data')
}

to get_learn_data {
  comment 'return: LearnData [ID,confidence]'
  '_get_image'
  return ('[data:makeList]' (at 2 _Data_buff) (100 - (at 3 _Data_buff)))
}

to get_track_data {
  comment 'return: LineData [angel,width,len]'
  '_get_image'
  local 'data' 0
  for i 3 {
    '[data:addLast]' (at (i + 2) _Data_buff) data
  }
  return data
}

to learn_object id {
  '_AILens setup'
  if (or (id > 5) (id < 1)) {
    sayIt '"Learn id out of range"'
  } else {
    '[sensors:i2cWrite]' _Camera_Add ('[data:asByteArray]' ('[data:makeList]' 10 id))
  }
}

to switch_function mode {
  '_AILens setup'
  comment 'mode'
  if (mode == 'Card') {
    mode = 2
  }
  if (mode == 'Face') {
    mode = 6
  }
  if (mode == 'Ball') {
    mode = 7
  }
  if (mode == 'Tracking') {
    mode = 8
  }
  if (mode == 'Color') {
    mode = 9
  }
  if (mode == 'Learn') {
    mode = 10
  }
  '[sensors:i2cWrite]' _Camera_Add ('[data:asByteArray]' ('[data:makeList]' (hexToInt '20') mode))
}


module APDS9960 Input
author wwj718
version 1 0 
description ''
variables _APDS9960_ADDR '_APDS9960 initialized' 

	spec 'r' 'get hue' 'APDS9960 get hue'
	spec 'r' 'get color' 'APDS9960 get color name'
	spec ' ' '_APDS9960 setup' '_APDS9960 setup'
	spec 'r' '_i2cread_color' '_i2cread_color _ _' 'auto auto' 0 0
	spec 'r' '__rgbtohsl' '_rgbtohsl _ _ _' 'auto auto auto' 0 0 0

to '_APDS9960 setup' {
  if ((v '_APDS9960 initialized') == 0) {
    comment '__initmodule'
    _APDS9960_ADDR = (hexToInt '39')
    local 'APDS9960_ATIME' (hexToInt '81')
    local 'APDS9960_CONTROL' (hexToInt '8f')
    local 'APDS9960_ENABLE' (hexToInt '80')
    local 'APDS9960_GCONF4' (hexToInt 'ab')
    local 'APDS9960_AICLEAR' (hexToInt 'e7')
    '[sensors:i2cWrite]' _APDS9960_ADDR ('[data:asByteArray]' ('[data:makeList]' APDS9960_ATIME 252))
    '[sensors:i2cWrite]' _APDS9960_ADDR ('[data:asByteArray]' ('[data:makeList]' APDS9960_CONTROL (hexToInt '03')))
    '[sensors:i2cWrite]' _APDS9960_ADDR ('[data:asByteArray]' ('[data:makeList]' APDS9960_ENABLE (hexToInt '00')))
    '[sensors:i2cWrite]' _APDS9960_ADDR ('[data:asByteArray]' ('[data:makeList]' APDS9960_GCONF4 (hexToInt '00')))
    '[sensors:i2cWrite]' _APDS9960_ADDR ('[data:asByteArray]' ('[data:makeList]' APDS9960_AICLEAR (hexToInt '00')))
    '[sensors:i2cWrite]' _APDS9960_ADDR ('[data:asByteArray]' ('[data:makeList]' APDS9960_ENABLE (hexToInt '01')))
    comment '__colormode'
    local 'tmp' (('_i2cread_color' _APDS9960_ADDR APDS9960_ENABLE) | (hexToInt '2'))
    comment '__i2cwrite_color'
    '[sensors:i2cWrite]' _APDS9960_ADDR ('[data:asByteArray]' ('[data:makeList]' APDS9960_ENABLE tmp))
    '_APDS9960 initialized' = 1
  }
}

to '__rgbtohsl' r g b {
  local 'hue' 0
  local 'R' ((r * 100) / 255)
  local 'G' ((g * 100) / 255)
  local 'B' ((b * 100) / 255)
  local 'maxVal' (maximum R (maximum G B))
  local 'minVal' (minimum R (minimum G B))
  local 'delta' (maxVal - minVal)
  if (delta <= 0) {
    return 0
  }
  if (and (maxVal == R) (G >= B)) {
    return ((60 * (((G - B) * 100) / delta)) / 100)
  }
  if (and (maxVal == R) (G < B)) {
    return (((60 * (((G - B) * 100) / delta)) + (360 * 100)) / 100)
  }
  if (maxVal == G) {
    return (((60 * (((B - R) * 100) / delta)) + (120 * 100)) / 100)
  }
  if (maxVal == B) {
    return (((60 * (((R - G) * 100) / delta)) + (240 * 100)) / 100)
  }
}

to '_i2cread_color' addr reg {
  local 'tmp' (newList 1)
  '[sensors:i2cWrite]' addr ('[data:asByteArray]' ('[data:makeList]' reg))
  '[sensors:i2cRead]' addr tmp
  return (at 1 tmp)
}

to 'get color' {
  local 'hue' ('get hue')
  if (or (and (hue > 340) (hue < 360)) (hue < 20)) {
    return 'red'
  }
  if (and (hue > 120) (hue < 180)) {
    return 'green'
  }
  if (and (hue > 30) (hue < 120)) {
    return 'yellow'
  }
  return 'No color'
}

to 'get hue' {
  '_APDS9960 setup'
  local 'APDS9960_STATUS' (hexToInt '93')
  local 'APDS9960_CDATAL' (hexToInt '94')
  local 'APDS9960_CDATAH' (hexToInt '95')
  local 'APDS9960_RDATAL' (hexToInt '96')
  local 'APDS9960_RDATAH' (hexToInt '97')
  local 'APDS9960_GDATAL' (hexToInt '98')
  local 'APDS9960_GDATAH' (hexToInt '99')
  local 'APDS9960_BDATAL' (hexToInt '9a')
  local 'APDS9960_BDATAH' (hexToInt '9b')
  local 'tmp' (('_i2cread_color' _APDS9960_ADDR APDS9960_STATUS) & (hexToInt '1'))
  repeatUntil (0 != tmp) {
    waitMillis 1000
    tmp = (('_i2cread_color' _APDS9960_ADDR APDS9960_STATUS) & 1)
  }
  local 'c' (('_i2cread_color' _APDS9960_ADDR APDS9960_CDATAL) + (('_i2cread_color' _APDS9960_ADDR APDS9960_CDATAH) * 256))
  local 'r' (('_i2cread_color' _APDS9960_ADDR APDS9960_RDATAL) + (('_i2cread_color' _APDS9960_ADDR APDS9960_RDATAH) * 256))
  local 'g' (('_i2cread_color' _APDS9960_ADDR APDS9960_GDATAL) + (('_i2cread_color' _APDS9960_ADDR APDS9960_GDATAH) * 256))
  local 'b' (('_i2cread_color' _APDS9960_ADDR APDS9960_BDATAL) + (('_i2cread_color' _APDS9960_ADDR APDS9960_BDATAH) * 256))
  local 'avg' (c / 3)
  r = ((r * 255) / avg)
  g = ((g * 255) / avg)
  b = ((b * 255) / avg)
  return ('__rgbtohsl' r g b)
}


module Distance Input
author 'Joan Guillén & Josep Ferràndiz'
version 1 0 
tags sensor 'hc-sr04' distance ultrasound 
description 'Support for the HC-SR04 ultrasound distance sensor.'

	spec 'r' 'distance (cm)' 'distance (cm) trigger _ echo _' 'auto auto' 2 4

to 'distance (cm)' trig ech {
  comment 'Contributed by Joan Guillén and Josep Ferràndiz'
  digitalWriteOp trig false
  waitMicros 2
  digitalWriteOp trig true
  waitMicros 50
  digitalWriteOp trig false
  local 'start' (microsOp)
  waitUntil (or (not (digitalReadOp ech)) (((microsOp) - start) > 23320))
  waitUntil (or (digitalReadOp ech) (((microsOp) - start) > 23320))
  local 'init' (microsOp)
  waitUntil (or (not (digitalReadOp ech)) (((microsOp) - init) > 23320))
  local 'end' (microsOp)
  return ((10 * (end - init)) / 583)
}


module HT16K33 Output
author wwj718
version 1 0 
description ''
variables _HT16K33_ADDR _HT16K33Buf '_HT16K33 initialized' 

	spec ' ' '_HT16K33 setup' '_HT16K33 setup'
	spec ' ' 'set matrix clear' 'set matrix (8x16) clear'
	spec ' ' 'set matrix draw' 'set matrix (8x16) draw x _ y _' 'num num' 0 0

to '_HT16K33 setup' {
  if ((v '_HT16K33 initialized') == 0) {
    comment '__initmodule'
    _HT16K33_ADDR = (hexToInt '70')
    _HT16K33Buf = (newList 17)
    local 'HT16K33_BLINK_CMD' (hexToInt '80')
    local 'HT16K33_BLINK_DISPLAYON' (hexToInt '01')
    local 'HT16K33_CMD_BRIGHTNESS' (hexToInt 'e0')
    '[sensors:i2cWrite]' _HT16K33_ADDR ('[data:asByteArray]' ('[data:makeList]' (hexToInt '21')))
    '[sensors:i2cWrite]' _HT16K33_ADDR ('[data:asByteArray]' ('[data:makeList]' (HT16K33_BLINK_CMD | (HT16K33_BLINK_DISPLAYON | (0 << 1)))))
    '[sensors:i2cWrite]' _HT16K33_ADDR ('[data:asByteArray]' ('[data:makeList]' (HT16K33_CMD_BRIGHTNESS | (hexToInt 'f'))))
    '_HT16K33 initialized' = 1
  }
}

to 'set matrix clear' {
  '_HT16K33 setup'
  _HT16K33Buf = (newList 17)
  atPut 1 _HT16K33Buf 0
  '[sensors:i2cWrite]' _HT16K33_ADDR ('[data:asByteArray]' _HT16K33Buf)
}

to 'set matrix draw' x y {
  comment 'x 0-15

y 0-7'
  '_HT16K33 setup'
  if (or (x < 0) (x > 15)) {
    sayIt 'Error: x 0-15'
    stopTask
  }
  if (or (y < 0) (y > 7)) {
    sayIt 'Error: Y 0-7'
    stopTask
  }
  local 'idx' ((y * 2) + (x / 8))
  local 'tmp' (at (idx + 2) _HT16K33Buf)
  tmp = (tmp | (1 << (x % 8)))
  atPut (idx + 2) _HT16K33Buf tmp
  atPut 1 _HT16K33Buf 0
  '[sensors:i2cWrite]' _HT16K33_ADDR ('[data:asByteArray]' _HT16K33Buf)
}


module 'LED Display' Output
author MicroBlocks
version 1 2 
tags pixel matrix led tft 
description 'Display primitives for the 5x5 LED display on the BBC micro:bit, Calliope mini and M5Atom Matrix. Boards with TFT displays (such as the Citilab ED1 or the M5Stack family) also support this primitives in a simulated "fat pixel" display.'
variables _stop_scrolling_text 

	spec ' ' '[display:mbDisplay]' 'display _' 'microbitDisplay' 15237440
	spec ' ' '[display:mbDisplayOff]' 'clear display'
	spec ' ' '[display:mbPlot]' 'plot x _ y _' 'num num' 3 3
	spec ' ' '[display:mbUnplot]' 'unplot x _ y _' 'num num' 3 3
	spec ' ' 'displayCharacter' 'display character _' 'str' 'A'
	spec ' ' 'scroll_text' 'scroll text _ : pausing _ ms' 'str num' 'HELLO ROSA!' 100
	spec ' ' 'stopScrollingText' 'stop scrolling'

to displayCharacter s {
  s = ('[data:join]' '' s)
  if ((size s) == 0) {
    '[display:mbDisplayOff]'
    return 0
  }
  '[display:mbDrawShape]' ('[display:mbShapeForLetter]' (at 1 s))
}

to scroll_text text optionalDelay {
  text = ('[data:join]' text '')
  delay = 100
  if ((pushArgCount) > 1) {
    delay = optionalDelay
  }
  _stop_scrolling_text = (booleanConstant false)
  local 'length' (size text)
  for position ((length * 6) + 6) {
    if _stop_scrolling_text {return 0}
    for i length {
      '[display:mbDrawShape]' ('[display:mbShapeForLetter]' ('[data:unicodeAt]' i text)) (((i * 6) + 2) - position) 1
    }
    waitMillis delay
  }
}

to stopScrollingText {
  _stop_scrolling_text = (booleanConstant true)
  waitMillis 10
  '[display:mbDisplayOff]'
}


module NeZha Output
author wwj718
version 1 1 
choices servoType '180' '270' '360' 
choices RJ_pin J1 J2 J3 J4 
choices inputPin J1 J2 
description '少年硅谷-火星环境探测挑战赛'
variables _NEZHA_ADDR '_NeZha initialized' 

	spec ' ' 'set motor speed' 'NeZha set motor _ speed to _ %' 'menu.range:1-4 num' 1 100
	spec ' ' 'stop motor' 'NeZha stop motor _' 'menu.range:1-4' 1
	spec ' ' 'stop all motors' 'NeZha stop all motors'
	spec ' ' 'set servo angle' 'NeZha set _ servo _ angle to _' 'menu.servoType menu.range:1-4 num' '360' 1 0
	spec ' ' 'set continuous rotation servo speed' 'NeZha set continuous rotation servo _ speed to _ %' 'menu.range:1-4 num' 1 0
	spec ' ' 'set led' 'NeZha LED _ toggle to _ brightness _ %' 'menu.RJ_pin bool auto' 'J1' true 100
	spec 'r' 'crash sensor state' 'NeZha crash sensor _ is pressed' 'menu.RJ_pin' 'J1'
	spec 'r' 'get distance' 'NeZha ultrasonic sensor _ distance(cm)' 'menu.RJ_pin' 'J1'
	spec 'r' 'get light level' 'NeZha light sensor _ light intensity(lux)' 'menu.inputPin' 'J1'
	spec ' ' 'set NeoPixel-8 at pin' 'NeZha set NeoPixel-8 at pin _' 'menu.RJ_pin' 'J1'
	spec ' ' 'set NeoPixel-8 Color' 'NeZha set NeoPixel-8 _ _ _ _ _ _ _ _' 'color color color color color color color color'
	spec ' ' '_NeZha setup' 'NeZha _NeZha setup'
	spec 'r' '_rescale' 'rescale _ from range ( _ , _ ) to ( _ , _ )' 'num num num num num' 0 0 0 0 0

to '_NeZha setup' {
  if ((v '_NeZha initialized') == 0) {
    _NEZHA_ADDR = (hexToInt '10')
    '_NeZha initialized' = 1
  }
}

to '_rescale' val in_min in_max out_min out_max {
  return ((((val - in_min) * (out_max - out_min)) / (in_max - in_min)) + out_min)
}

to 'crash sensor state' pin {
  '_NeZha setup'
  local 'target_pin' 0
  if (pin == 'J1') {
    target_pin = 8
  }
  if (pin == 'J2') {
    target_pin = 12
  }
  if (pin == 'J3') {
    target_pin = 14
  }
  if (pin == 'J4') {
    target_pin = 16
  }
  return (not (digitalReadOp target_pin))
}

to 'get distance' pin {
  '_NeZha setup'
  local 'target_pin' 0
  local 'pin_e' 0
  local 'pin_t' 0
  if (pin == 'J1') {
    pin_e = 8
    pin_t = 1
  }
  if (pin == 'J2') {
    pin_e = 12
    pin_t = 2
  }
  if (pin == 'J3') {
    pin_e = 14
    pin_t = 13
  }
  if (pin == 'J4') {
    pin_e = 16
    pin_t = 15
  }
  return ('distance (cm)' pin_t pin_e)
}

to 'get light level' pin {
  comment 'return: 0-16000 lux'
  '_NeZha setup'
  local 'target_pin' 0
  local 'final_val' 0
  if (pin == 'J1') {
    target_pin = 1
  }
  if (pin == 'J2') {
    target_pin = 2
  }
  local 'value' (analogReadOp target_pin)
  if (value <= 300) {
    final_val = (((value - 10) * (1600 - 0)) / ((300 - 10) + 0))
  } else {
    final_val = (((value - 300) * (14000 - 1600)) / ((1023 - 300) + 1600))
  }
  return (maximum final_val 0)
}

to 'set NeoPixel-8 Color' c1 c2 c3 c4 c5 c6 c7 c8 {
  setNeoPixelColors10 c1 c2 c3 c4 c5 c6 c7 c8
}

to 'set NeoPixel-8 at pin' pin {
  comment 'work with NeoPixel library!'
  local 'target_pin' 0
  if (pin == 'J1') {
    target_pin = 8
  }
  if (pin == 'J2') {
    target_pin = 12
  }
  if (pin == 'J3') {
    target_pin = 14
  }
  if (pin == 'J4') {
    target_pin = 16
  }
  neoPixelAttach 8 target_pin
}

to 'set continuous rotation servo speed' servo angle {
  comment 'motor (number): 1 2 3 4'
  comment 'speed (number): -100-100'
  if (or (angle < -100) (angle > 100)) {
    angle = 0
  }
  'set servo angle' '180' servo ('_rescale' angle -100 100 0 180)
}

to 'set led' pin state brightness {
  '_NeZha setup'
  local 'target_pin' 0
  comment 'brightness 0-100'
  if (or (brightness < 0) (brightness > 100)) {
    brightness = 0
  }
  if (pin == 'J1') {
    target_pin = 1
  }
  if (pin == 'J2') {
    target_pin = 2
  }
  if (pin == 'J3') {
    target_pin = 13
  }
  if (pin == 'J4') {
    target_pin = 15
  }
  if (state == (booleanConstant false)) {
    analogWriteOp target_pin 0
  } else {
    analogWriteOp target_pin ('_rescale' brightness 0 100 0 1023)
  }
}

to 'set motor speed' motor speed {
  '_NeZha setup'
  comment 'motor (number): 1 2 3 4'
  comment 'speed (number): -100-100'
  if (or (motor < 1) (motor > 4)) {
    motor = 1
  }
  if (or (speed < -100) (speed > 100)) {
    speed = 0
  }
  if (speed < 0) {
    '[sensors:i2cWrite]' _NEZHA_ADDR ('[data:asByteArray]' ('[data:makeList]' motor 2 (speed * -1) 0))
  } else {
    '[sensors:i2cWrite]' _NEZHA_ADDR ('[data:asByteArray]' ('[data:makeList]' motor 1 speed 0))
  }
}

to 'set servo angle' servo_type servo angle {
  '_NeZha setup'
  comment 'servo (number): 1 2 3 4'
  comment '''180'' ''270'' ''360''

str -> num'
  servo_type = (absoluteValue servo_type)
  if (or (servo < 1) (servo > 4)) {
    servo = 1
  }
  if (or (angle < 0) (angle > servo_type)) {
    angle = 0
  }
  '[sensors:i2cWrite]' _NEZHA_ADDR ('[data:asByteArray]' ('[data:makeList]' ((hexToInt '10') + (servo - 1)) ('_rescale' angle 0 servo_type 0 180) 0 0))
}

to 'stop all motors' {
  '_NeZha setup'
  for i 4 {
    'set motor speed' i 0
  }
}

to 'stop motor' index {
  '_NeZha setup'
  'set motor speed' index 0
}


module NeoPixel Output
author MicroBlocks
version 1 2 
tags led strip rgb string ws2812 
description 'Control NeoPixel (WS2812) RGB LED strips.
'
variables _np_pixels 

	spec ' ' 'neoPixelAttach' 'attach _ LED NeoPixel strip to pin _ : has white _' 'num auto bool' 10 '' false
	spec ' ' 'setNeoPixelColors10' 'set NeoPixels _ _ _ _ _ _ _ _ _ _' 'color color color color color color color color color color'
	spec ' ' 'clearNeoPixels' 'clear NeoPixels'
	spec ' ' 'neoPixelSetAllToColor' 'set all NeoPixels color _' 'color'
	spec ' ' 'setNeoPixelColor' 'set NeoPixel _ color _' 'num color' 1
	spec ' ' 'rotateNeoPixelsBy' 'rotate NeoPixels by _' 'auto' 1
	spec 'r' 'colorFromRGB' 'color r _ g _ b _ (0-255)' 'num num num' 0 100 100
	spec 'r' 'randomColor' 'random color'
	spec ' ' '_NeoPixel_ensureInitialized' '_NeoPixel_ensureInitialized'
	spec ' ' '_NeoPixel_rotate' '_NeoPixel_rotate_left _' 'bool' true
	spec ' ' '_NeoPixel_update' '_NeoPixel_update'

to '_NeoPixel_ensureInitialized' {
  if (_np_pixels == 0) {if ((boardType) == 'M5Atom-Matrix') {
    neoPixelAttach 25 '' false
  } ((boardType) == 'D1-Mini') {
    comment 'D1 mini kit'
    neoPixelAttach 7 15 false
  } else {
    neoPixelAttach 10 '' false
  }}
}

to '_NeoPixel_rotate' left {
  '_NeoPixel_ensureInitialized'
  local 'length' (size _np_pixels)
  if left {
    local 'first' (at 1 _np_pixels)
    for i (length - 1) {
      atPut i _np_pixels (at (i + 1) _np_pixels)
    }
    atPut length _np_pixels first
  } else {
    local 'last' (at length _np_pixels)
    for i (length - 1) {
      atPut ((length - i) + 1) _np_pixels (at (length - i) _np_pixels)
    }
    atPut 1 _np_pixels last
  }
}

to '_NeoPixel_update' {
  '[display:neoPixelSend]' _np_pixels
  waitMicros 100
}

to clearNeoPixels {
  '_NeoPixel_ensureInitialized'
  fillList _np_pixels 0
  '_NeoPixel_update'
}

to colorFromRGB r g b {
  r = (maximum 0 (minimum r 255))
  g = (maximum 0 (minimum g 255))
  b = (maximum 0 (minimum b 255))
  return (((r << 16) | (g << 8)) | b)
}

to neoPixelAttach number pinNumber optionalHasWhite {
  hasWhite = false
  if ((pushArgCount) > 2) {
    hasWhite = optionalHasWhite
  }
  if (or (_np_pixels == 0) (number != (size _np_pixels))) {
    _np_pixels = (newList number)
  }
  fillList _np_pixels 0
  '[display:neoPixelSetPin]' pinNumber hasWhite
}

to neoPixelSetAllToColor color {
  '_NeoPixel_ensureInitialized'
  fillList _np_pixels color
  '_NeoPixel_update'
}

to randomColor {
  local 'n1' (random 100 200)
  local 'n2' (random 0 100)
  if (1 == (random 1 3)) {
    return ((n1 << 16) | (n2 << 8))
  } (1 == (random 1 2)) {
    return ((n2 << 16) | n1)
  } else {
    return ((n1 << 8) | n2)
  }
}

to rotateNeoPixelsBy n {
  '_NeoPixel_ensureInitialized'
  repeat (absoluteValue n) {
    '_NeoPixel_rotate' (n > 0)
  }
  '_NeoPixel_update'
}

to setNeoPixelColor i color {
  '_NeoPixel_ensureInitialized'
  if (and (1 <= i) (i <= (size _np_pixels))) {
    atPut i _np_pixels color
    '_NeoPixel_update'
  }
}

to setNeoPixelColors10 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 {
  '_NeoPixel_ensureInitialized'
  if ((size _np_pixels) >= 1) {
    atPut 1 _np_pixels c1
  }
  if ((size _np_pixels) >= 2) {
    atPut 2 _np_pixels c2
  }
  if ((size _np_pixels) >= 3) {
    atPut 3 _np_pixels c3
  }
  if ((size _np_pixels) >= 4) {
    atPut 4 _np_pixels c4
  }
  if ((size _np_pixels) >= 5) {
    atPut 5 _np_pixels c5
  }
  if ((size _np_pixels) >= 6) {
    atPut 6 _np_pixels c6
  }
  if ((size _np_pixels) >= 7) {
    atPut 7 _np_pixels c7
  }
  if ((size _np_pixels) >= 8) {
    atPut 8 _np_pixels c8
  }
  if ((size _np_pixels) >= 9) {
    atPut 9 _np_pixels c9
  }
  if ((size _np_pixels) >= 10) {
    atPut 10 _np_pixels c10
  }
  '_NeoPixel_update'
}


module Radio Comm
author MicroBlocks
version 1 2 
tags radio communication messaging network 
description 'Send and receive messages between micro:bit boards via their built-in radio system.'

	spec ' ' '[radio:sendInteger]' 'radio send number _' 'num' 123
	spec ' ' '[radio:sendString]' 'radio send string _' 'str' 'Hello!'
	spec ' ' '[radio:sendPair]' 'radio send pair _ = _' 'str num' 'light' 10
	spec 'r' '[radio:messageReceived]' 'radio message received?'
	spec 'r' '[radio:receivedInteger]' 'radio last number'
	spec 'r' '[radio:receivedString]' 'radio last string'
	spec ' ' '[radio:setGroup]' 'radio set group _ (0-255)' 'num' 0
	spec ' ' '[radio:setPower]' 'radio set power (0-7) _' 'num' 4
	spec 'r' '_signalStrength' '_radio last signal strength'
	spec 'r' '_radioLastSenderID' '_radio last sender ID'
	spec 'r' '_radioMyID' '_radio my ID'
	spec 'r' '_receivedMessageType' '_radio last message type'
	spec ' ' '_setChannel' '_radio set channel (0-83) _' 'num' 7

to '_radioLastSenderID' {
  return ('[radio:lastMessageID]')
}

to '_radioMyID' {
  return ('[radio:deviceID]')
}

to '_receivedMessageType' {
  return ('[radio:receivedMessageType]')
}

to '_setChannel' channel {
  '[radio:setChannel]' channel
}

to '_signalStrength' {
  return ('[radio:signalStrength]')
}


module Trackbit Input
author wwj718
version 1 1 
choices channel_state '●' '◌' 
description ''
variables _TrackBit_state_value '_Trackbit initialized' 

	spec 'r' 'Trackbit channel' 'Trackbit channel _ is _' 'menu.range:1-4 menu.channel_state' 1 '◌'
	spec 'r' 'Trackbit is' 'Trackbit is _ _ _ _' 'menu.channel_state menu.channel_state menu.channel_state menu.channel_state' '◌' '◌' '◌' '◌'
	spec ' ' '_Trackbit setup' '_Trackbit setup'
	spec ' ' 'Get a Trackbit state value' 'Get a Trackbit state value'

to 'Get a Trackbit state value' {
  '_Trackbit setup'
  local 'tmp' (newList 1)
  '[sensors:i2cWrite]' (hexToInt '1a') (hexToInt '4')
  '[sensors:i2cRead]' (hexToInt '1a') tmp
  _TrackBit_state_value = (at 1 tmp)
  waitMillis 5
}

to 'Trackbit channel' channel state {
  '_Trackbit setup'
  if (state == '●') {
    state = 1
  } else {
    state = 0
  }
  return (((_TrackBit_state_value >> (channel - 1)) & 1) == state)
}

to 'Trackbit is' channel1_state channel2_state channel3_state channel4_state {
  '_Trackbit setup'
  if (channel1_state == '●') {
    channel1_state = 1
  } else {
    channel1_state = 0
  }
  if (channel2_state == '●') {
    channel2_state = 1
  } else {
    channel2_state = 0
  }
  if (channel3_state == '●') {
    channel3_state = 1
  } else {
    channel3_state = 0
  }
  if (channel4_state == '●') {
    channel4_state = 1
  } else {
    channel4_state = 0
  }
  local 'tmp' _TrackBit_state_value
  return (and (and (((tmp >> 3) & 1) == channel4_state) (((tmp >> 2) & 1) == channel3_state)) (and (((tmp >> 1) & 1) == channel2_state) (((tmp >> 0) & 1) == channel1_state)))
}

to '_Trackbit setup' {
  if ((v '_Trackbit initialized') == 0) {
    _TrackBit_state_value = 0
    '_Trackbit initialized' = 1
  }
}

