module main
author unknown
version 1 0 
description ''
variables data buff 

script 60 40 {
whenStarted
buff = 0
'[serial:open]' 9600
forever {
  buff = ('[serial:read]')
  sayIt ('[serial:read]')
  if ((size buff) > 0) {
    local 'var' (newList (size buff))
    for i (size buff) {
      atPut i var (at i buff)
    }
    data = ('[data:unicodeString]' var)
    sayIt ('[data:unicodeString]' var)
    data = ('[data:unicodeString]' var)
  }
  waitMillis 10
}
}

script 388 568 {
whenCondition (data == 'L')
'左转'
}

script 215 573 {
whenCondition (data == 'R')
'右转'
}

script 62 591 {
whenCondition (data == 'F')
'前进'
}

script 202 685 {
whenCondition (data == 'S')
'停止'
}

script 62 691 {
whenCondition (data == 'B')
'后退'
}


module Tone Output
author MicroBlocks
version 1 8 
tags tone sound music audio note speaker 
choices tone_NoteName c 'c#' d 'd#' e f 'f#' g 'g#' a 'a#' b 
description 'Audio tone generation. Make music with MicroBlocks!'
variables _tonePin _toneInitalized _toneLoopOverhead _toneNoteNames _toneArezzoNotes _toneFrequencies 

  spec ' ' 'play tone' 'play note _ octave _ for _ ms' 'str.tone_NoteName num num' 'c' 0 500
  spec ' ' 'playMIDIKey' 'play midi key _ for _ ms' 'num num' 60 500
  spec ' ' 'play frequency' 'play frequency _ for _ ms' 'num num' 261 500
  space
  spec ' ' 'startTone' 'start tone _ Hz' 'num' 440
  spec ' ' 'stopTone' 'stop tone'
  space
  spec ' ' 'attach buzzer to pin' 'attach buzzer to pin _' 'auto' ''
  space
  spec 'r' '_measureLoopOverhead' '_measureLoopOverhead'
  spec 'r' '_baseFreqForNote' '_baseFreqForNote _' 'auto' 'c'
  spec 'r' '_baseFreqForSemitone' '_baseFreqForSemitone _' 'num' 0
  spec ' ' '_toneLoop' '_toneLoop _ for _ ms' 'num num' 440000 100
  spec 'r' '_trimmedLowercase' '_trimmedLowercase _' 'str' 'A. b C...'

to '_baseFreqForNote' note {
  comment 'Return the frequency for the given note in the middle-C octave
scaled by 1000. For example, return 440000 (440Hz) for A.
Note names may be upper or lower case. Note names
may be followed by # for a sharp or b for a flat.'
  local 'normalized note' ('_trimmedLowercase' note)
  if (_toneNoteNames == 0) {
    _toneNoteNames = ('[data:makeList]' 'c' 'c#' 'd' 'd#' 'e' 'f' 'f#' 'g' 'g#' 'a' 'a#' 'b' 'c_' 'db' 'd_' 'eb' 'e_' 'e#' 'f_' 'gb' 'g_' 'ab' 'a_' 'bb' 'b_' 'b#')
    _toneArezzoNotes = ('[data:makeList]' 'do' 'do#' 're' 're#' 'mi' 'fa' 'fa#' 'sol' 'sol#' 'la' 'la#' 'si' 'do_' 'dob' 're_' 'reb' 'mi_' 'mi#' 'fa_' 'solb' 'sol_' 'lab' 'la_' 'sib' 'si_' 'si#')
  }
  if (('[data:find]' (v 'normalized note') _toneArezzoNotes) > 0) {
    return ('_baseFreqForSemitone' ('[data:find]' (v 'normalized note') _toneArezzoNotes))
  } else {
    return ('_baseFreqForSemitone' ('[data:find]' (v 'normalized note') _toneNoteNames))
  }
}

to '_baseFreqForSemitone' semitone {
  if (_toneFrequencies == 0) {_toneFrequencies = ('[data:makeList]' 261626 277183 293665 311127 329628 349228 369994 391995 415305 440000 466164 493883 246942 277183 277183 311127 311127 349228 329628 369994 369994 415305 415305 466164 466164 523252)}
  if (and (1 <= semitone) (semitone <= (size _toneFrequencies))) {
    return (at semitone _toneFrequencies)
  } else {
    comment 'Bad note name; return 10 Hz'
    return 10000
  }
}

to '_measureLoopOverhead' {
  comment 'Measure the loop overhead on this device'
  local 'halfCycle' 100
  local 'startT' (microsOp)
  repeat 100 {
    digitalWriteOp _tonePin false
    waitMicros halfCycle
    digitalWriteOp _tonePin false
    waitMicros halfCycle
  }
  local 'usecs' ((microsOp) - startT)
  return ((usecs - 20000) / 200)
}

to '_toneLoop' scaledFreq ms {
  if (_toneInitalized == 0) {'attach buzzer to pin' ''}
  if ('[io:hasTone]') {
    '[io:playTone]' _tonePin (scaledFreq / 1000)
    waitMillis ms
    '[io:playTone]' _tonePin 0
  } else {
    local 'halfCycle' ((500000000 / scaledFreq) - _toneLoopOverhead)
    local 'cycles' ((ms * 500) / halfCycle)
    repeat cycles {
      digitalWriteOp _tonePin true
      waitMicros halfCycle
      digitalWriteOp _tonePin false
      waitMicros halfCycle
    }
  }
}

to '_trimmedLowercase' s {
  comment 'Return a copy of the given string without whitespace
or periods and all lowercase.'
  local 'result' (newList (size s))
  '[data:delete]' 'all' result
  for i (size s) {
    local 'ch' ('[data:unicodeAt]' i s)
    if (and (ch > 32) (ch != 46)) {
      if (and (65 <= ch) (ch <= 90)) {ch = (ch + 32)}
      '[data:addLast]' ch result
    }
  }
  return ('[data:unicodeString]' result)
}

to 'attach buzzer to pin' pinNumber {
  if (pinNumber == '') {
    comment 'Pin number not specified; use default pin for this device'
    if ((boardType) == 'Citilab ED1') {
      _tonePin = 26
    } ((boardType) == 'M5Stack-Core') {
      _tonePin = 25
    } ((boardType) == 'M5StickC') {
      _tonePin = 26
    } ((boardType) == 'Calliope') {
      digitalWriteOp 23 true
      digitalWriteOp 24 true
      _tonePin = 25
    } ((boardType) == 'D1-Mini') {
      _tonePin = 12
    } else {
      _tonePin = -1
    }
  } else {
    _tonePin = pinNumber
  }
  _toneLoopOverhead = ('_measureLoopOverhead')
  _toneInitalized = (booleanConstant true)
}

to 'play frequency' freq ms {
  '_toneLoop' (freq * 1000) ms
}

to 'play tone' note octave ms {
  local 'freq' ('_baseFreqForNote' note)
  if (freq <= 10000) {
    waitMillis ms
    return 0
  }
  if (octave < 0) {
    repeat (absoluteValue octave) {
      freq = (freq / 2)
    }
  }
  repeat octave {
    freq = (freq * 2)
  }
  '_toneLoop' freq ms
}

to playMIDIKey key ms {
  local 'freq' ('_baseFreqForSemitone' ((key % 12) + 1))
  local 'octave' ((key / 12) - 5)
  if (octave < 0) {
    repeat (absoluteValue octave) {
      freq = (freq / 2)
    }
  }
  repeat octave {
    freq = (freq * 2)
  }
  '_toneLoop' freq ms
}

to startTone freq {
  if (_toneInitalized == 0) {'attach buzzer to pin' ''}
  if ('[io:hasTone]') {'[io:playTone]' _tonePin freq}
}

to stopTone {
  startTone 0
}


module WuKong2040 Output
author ELECFREAKS
version 1 1 
depends Tone 
tags pico picow wukong2040 wukong2040 pico picow tone 
choices wk2040_rainbowLEDMenu '0' '1' all 
choices wk2040_motorMenu M1 M2 M3 M4 
description 'ELECFREAKS WuKong2040 multi-function expansion board.

Features:
  Raspberry Pi Pico/PicoW
  14 × Expansion GPIO Ports (including SPI\IIC\UART)
   4 × Motor Driving
   2 × Rainbow LED
   2 × Button
   1 × Buzzer

Power Supply:
  18650 Lithium Battery

Pins:
  Buzzer = 9
  Button_A = 18
  Button_B = 19
  RGB_LED = 22
  Motor_M1 = 20, 21
  Motor_M2 = 10, 11
  Motor_M3 = 14, 15
  Motor_M4 = 12, 13

  UART_TX = 0
  UART_RX = 1

  SPI_SCK = 2
  SPI_MOSI = 3
  SPI_MISO = 4
  SPI_SS = 5

  IIC_SDA = 16
  IIC_SCL = 17

Official website:
https://www.elecfreaks.com/

Wiki reference:
http://wiki.elecfreaks.com/en/pico/extension-module/wukong2040-pico
'
variables _wk2040_pixels 

  spec ' ' 'wk2040_set_LED_color' 'WuKong2040 rainbowLED _ color to _' 'menu.wk2040_rainbowLEDMenu color' '0'
  spec ' ' 'wk2040_set_LED_RGB' 'WuKong2040 rainbowLED _ R _ G _ B _ (0~255)' 'menu.wk2040_rainbowLEDMenu num num num' '0' 0 0 255
  spec ' ' 'wk2040_turn_off_all_LEDs' 'WuKong2040 clear all rainbowLED'
  space
  spec ' ' 'wk2040_set_motor_speed' 'WuKong2040 motor _ speed to _ (-100~100)' 'menu.wk2040_motorMenu num' 'M1' 50
  spec ' ' 'WuKong2040 stop motor' 'WuKong2040 stop motor _' 'menu.wk2040_motorMenu' 'M1'
  spec ' ' 'wk2040_stop_all_motors' 'WuKong2040 stop all motors'
  space
  spec ' ' 'wk2040_beat' 'WuKong2040 buzzer beep _ ms' 'auto' '100'
  space
  spec ' ' '_wk2040_initLEDs' '_wk2040_initLEDs'
  spec 'r' '_wk2040_colorFromRGB' '_color r _ g _ b _ (0-255)' 'num num num' 0 100 100

to 'WuKong2040 stop motor' motor {
  if ('M1' == motor) {
    '_wk2040_set_motor_speed' 20 21 0
  } ('M2' == motor) {
    '_wk2040_set_motor_speed' 10 11 0
  } ('M3' == motor) {
    '_wk2040_set_motor_speed' 15 14 0
  } ('M4' == motor) {
    '_wk2040_set_motor_speed' 13 12 0
  }
}

to '_wk2040_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 '_wk2040_initLEDs' {
  '[display:neoPixelSetPin]' -1 false
  if (not (isType _wk2040_pixels 'list')) {
    _wk2040_pixels = (newList 2)
  }
}

to '_wk2040_set_motor_speed' pin1 pin2 speed {
  if (speed < 0) {
    analogWriteOp pin1 ('[misc:rescale]' (absoluteValue speed) 0 100 0 1023)
    analogWriteOp pin2 0
  } else {
    analogWriteOp pin2 ('[misc:rescale]' speed 0 100 0 1023)
    analogWriteOp pin1 0
  }
}

to wk2040_beat duration {
  local 'pin_buzzer' 9
  local 'end time' ((millisOp) + duration)
  repeatUntil ((millisOp) >= (v 'end time')) {
    digitalWriteOp pin_buzzer true
    waitMicros 400
    digitalWriteOp pin_buzzer false
    waitMicros 400
  }
}

to wk2040_set_LED_RGB num r g b {
  wk2040_set_LED_color num ('_wk2040_colorFromRGB' r g b)
}

to wk2040_set_LED_color num color {
  '_wk2040_initLEDs'
  if (num == '0') {
    atPut 1 _wk2040_pixels color
    '[display:neoPixelSend]' _wk2040_pixels
    waitMicros 150
  }
  if (num == '1') {
    atPut 'last' _wk2040_pixels color
    '[display:neoPixelSend]' _wk2040_pixels
    waitMicros 150
  }
  if (num == 'all') {
    atPut 'all' _wk2040_pixels color
    '[display:neoPixelSend]' _wk2040_pixels
    waitMicros 150
  }
}

to wk2040_set_motor_speed motor speed {
  if ('M1' == motor) {
    '_wk2040_set_motor_speed' 20 21 speed
  } ('M2' == motor) {
    '_wk2040_set_motor_speed' 10 11 speed
  } ('M3' == motor) {
    '_wk2040_set_motor_speed' 15 14 speed
  } ('M4' == motor) {
    '_wk2040_set_motor_speed' 13 12 speed
  }
}

to wk2040_stop_all_motors {
  wk2040_set_motor_speed 'M1' 0
  wk2040_set_motor_speed 'M2' 0
  wk2040_set_motor_speed 'M3' 0
  wk2040_set_motor_speed 'M4' 0
}

to wk2040_turn_off_all_LEDs {
  wk2040_set_LED_color 'all' (colorSwatch 0 0 0 255)
}


module '小车库'
author unknown
version 1 0 
description ''

  spec ' ' '停止' '停止'
  spec ' ' '前进' '前进'
  spec ' ' '右转' '右转'
  spec ' ' '后退' '后退'
  spec ' ' '左转' '左转'

to '停止' {
  wk2040_stop_all_motors
}

to '前进' {
  wk2040_set_motor_speed 'M2' -50
  wk2040_set_motor_speed 'M4' 50
  wk2040_set_motor_speed 'M1' 50
  wk2040_set_motor_speed 'M3' -50
}

to '右转' {
  wk2040_set_motor_speed 'M3' -50
  wk2040_set_motor_speed 'M1' 50
  wk2040_set_motor_speed 'M4' -50
  wk2040_set_motor_speed 'M2' 50
}

to '后退' {
  wk2040_set_motor_speed 'M2' 50
  wk2040_set_motor_speed 'M4' -50
  wk2040_set_motor_speed 'M1' -50
  wk2040_set_motor_speed 'M3' 50
}

to '左转' {
  wk2040_set_motor_speed 'M1' -50
  wk2040_set_motor_speed 'M3' 50
  wk2040_set_motor_speed 'M2' -50
  wk2040_set_motor_speed 'M4' 50
}

