diff options
124 files changed, 7307 insertions, 640 deletions
diff --git a/.gitignore b/.gitignore index 95be7bf651..6224e57cdb 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ ###################### *.swp +# Build directory +###################### +build/ @@ -1,5 +1,8 @@ The Micro Python project ======================== +<p align="center"> + <img src="https://raw2.github.com/micropython/micropython/master/logo/upython-with-micro.jpg" alt="MicroPython Logo"/> +</p> This is the Micro Python project, which aims to put an implementation of Python 3.x on a microcontroller. diff --git a/logo/micropythonpowered-art.png b/logo/micropythonpowered-art.png Binary files differnew file mode 100644 index 0000000000..9045bb0a43 --- /dev/null +++ b/logo/micropythonpowered-art.png diff --git a/logo/upython-with-micro.jpg b/logo/upython-with-micro.jpg Binary files differnew file mode 100644 index 0000000000..4984d8e2f2 --- /dev/null +++ b/logo/upython-with-micro.jpg diff --git a/logo/upython-with-micro.png b/logo/upython-with-micro.png Binary files differnew file mode 100644 index 0000000000..2b3431cbdd --- /dev/null +++ b/logo/upython-with-micro.png diff --git a/logo/vector-logo-2.png b/logo/vector-logo-2.png Binary files differindex 3ad2383ff5..72ce88e1d5 100644 --- a/logo/vector-logo-2.png +++ b/logo/vector-logo-2.png diff --git a/logo/vector-logo-3.png b/logo/vector-logo-3.png Binary files differnew file mode 100644 index 0000000000..ba75b05624 --- /dev/null +++ b/logo/vector-logo-3.png diff --git a/logo/vector-logo-inkscape_master.svg b/logo/vector-logo-inkscape_master.svg index 19415d41b7..ddcf741178 100644 --- a/logo/vector-logo-inkscape_master.svg +++ b/logo/vector-logo-inkscape_master.svg @@ -15,8 +15,8 @@ height="779.328" id="svg2" inkscape:version="0.48.4 r9939" - sodipodi:docname="vector-logo-inkscape_master.svg" - inkscape:export-filename="R:\Mark_Sector\!!Projects-2\microPython\Logo\vector-logo-4.png" + sodipodi:docname="vector-logo-inkscape_master-2.svg" + inkscape:export-filename="C:\Users\user3\Documents\GitHub\micropython\logo\vector-logo-2.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90"> <sodipodi:namedview @@ -28,20 +28,110 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1609" + inkscape:window-width="1414" inkscape:window-height="1086" id="namedview127" showgrid="false" - inkscape:zoom="1.1668212" - inkscape:cx="347.36024" - inkscape:cy="357.11268" + inkscape:zoom="0.80389336" + inkscape:cx="-0.14388424" + inkscape:cy="205.20636" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="0" - inkscape:current-layer="layer6" /> + inkscape:current-layer="layer3" /> <defs id="defs4"> <linearGradient + id="linearGradient5215"> + <stop + style="stop-color:#f1f1f1;stop-opacity:1;" + offset="0" + id="stop5217" /> + <stop + style="stop-color:#000000;stop-opacity:0.4054054;" + offset="1" + id="stop5219" /> + </linearGradient> + <linearGradient + id="linearGradient5205"> + <stop + style="stop-color:#d8d8d8;stop-opacity:1;" + offset="0" + id="stop5207" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop5209" /> + </linearGradient> + <linearGradient + id="linearGradient4753"> + <stop + id="stop4755" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759" /> + <stop + id="stop4757" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient4249"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253" /> + </linearGradient> + <linearGradient + id="linearGradient4233"> + <stop + style="stop-color:#6f6f6f;stop-opacity:1;" + offset="0" + id="stop4235" /> + <stop + id="stop4247" + offset="0.0808401" + style="stop-color:#ffffff;stop-opacity:1" /> + <stop + id="stop4245" + offset="0.125" + style="stop-color:#616161;stop-opacity:1;" /> + <stop + id="stop4243" + offset="0.25" + style="stop-color:#535353;stop-opacity:1;" /> + <stop + id="stop4241" + offset="0.5" + style="stop-color:#373737;stop-opacity:1;" /> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="1" + id="stop4237" /> + </linearGradient> + <linearGradient + id="linearGradient4029"> + <stop + style="stop-color:#3e3e3e;stop-opacity:1;" + offset="0" + id="stop4031" /> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="1" + id="stop4033" /> + </linearGradient> + <linearGradient id="linearGradient4981"> <stop style="stop-color:#370000;stop-opacity:1;" @@ -364,6 +454,1786 @@ x2="273.90927" y2="601.64478" gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4035" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249" + id="linearGradient4255" + x1="48.514041" + y1="697.80837" + x2="326.39456" + y2="697.80837" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-2" + id="linearGradient4332-7" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-2"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-2" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-9" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-9" + id="linearGradient4332-1" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-9"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-6" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-98" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-4" + id="linearGradient4332-5" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-4"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-9" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-1" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-3" + id="linearGradient4332-8" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-3"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-93" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-96" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-7" + id="linearGradient4332-9" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-7"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-69" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-3" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-6" + id="linearGradient4332-6" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-6"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-5" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-8" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-63" + id="linearGradient4332-61" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-63"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-3" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-5" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-5" + id="linearGradient4332-82" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-5"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-36" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-18" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-62" + id="linearGradient4332-4" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-62"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-91" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-50" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-29" + id="linearGradient4332-49" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-29"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-34" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-4" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-42" + id="linearGradient4332-63" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-42"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-8" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-87" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-57" + id="linearGradient4332-2" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-57"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-4" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-44" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-0" + id="linearGradient4332-93" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-0"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-7" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-7" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-38" + id="linearGradient4332-0" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-38"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-25" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-2" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-53" + id="linearGradient4332-97" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + id="linearGradient4249-53"> + <stop + style="stop-color:#afafaf;stop-opacity:1;" + offset="0" + id="stop4251-43" /> + <stop + style="stop-color:#0b0b0b;stop-opacity:1;" + offset="1" + id="stop4253-21" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249" + id="linearGradient4627" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-2" + id="linearGradient4629" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(16.462108,6.0241868)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-9" + id="linearGradient4631" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(32.653947,11.977068)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-4" + id="linearGradient4633" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(49.0839,18.168066)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-3" + id="linearGradient4635" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(65.513853,24.359063)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-7" + id="linearGradient4637" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(81.467577,30.311944)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-6" + id="linearGradient4639" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(97.89753,36.02671)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-63" + id="linearGradient4641" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(115.04183,41.741477)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-5" + id="linearGradient4643" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(130.99555,47.694359)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-62" + id="linearGradient4645" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(147.66362,53.647241)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-29" + id="linearGradient4647" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(164.09357,59.838237)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-42" + id="linearGradient4649" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(180.52353,65.314889)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-57" + id="linearGradient4651" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(196.71536,71.744001)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-0" + id="linearGradient4653" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(212.66909,77.934999)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-38" + id="linearGradient4655" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(229.57527,82.935419)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-53" + id="linearGradient4657" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(246.00523,89.126416)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4692" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4695" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4698" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4701" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4704" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4707" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4710" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4713" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4716" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4719" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4722" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4725" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4728" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4731" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029" + id="linearGradient4734" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753" + id="linearGradient4737" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4029-2" + id="linearGradient4704-3" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-94.138416,56.066335)" + x1="50.162903" + y1="641.96503" + x2="305.03671" + y2="733.44366" /> + <linearGradient + id="linearGradient4029-2"> + <stop + style="stop-color:#3e3e3e;stop-opacity:1;" + offset="0" + id="stop4031-1" /> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="1" + id="stop4033-0" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-0" + id="linearGradient4737-4" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-0"> + <stop + id="stop4755-7" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-5" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-9" /> + <stop + id="stop4757-0" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(-94.138416,56.066335)" + gradientUnits="userSpaceOnUse" + id="linearGradient4785" + xlink:href="#linearGradient4753-0" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-09" + id="linearGradient4737-2" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-09"> + <stop + id="stop4755-8" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-9" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-1" /> + <stop + id="stop4757-7" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(16.293772,-6.7832111)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835" + xlink:href="#linearGradient4753-09" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-07" + id="linearGradient4737-3" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-07"> + <stop + id="stop4755-6" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-6" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-0" /> + <stop + id="stop4757-2" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(32.866764,-12.497978)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-8" + xlink:href="#linearGradient4753-07" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-9" + id="linearGradient4737-8" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-9"> + <stop + id="stop4755-9" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-94" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-2" /> + <stop + id="stop4757-08" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(49.296717,-18.212744)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-7" + xlink:href="#linearGradient4753-9" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-3" + id="linearGradient4737-7" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-3"> + <stop + id="stop4755-0" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-7" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-6" /> + <stop + id="stop4757-4" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(65.72667,-24.403741)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-2" + xlink:href="#linearGradient4753-3" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-1" + id="linearGradient4737-9" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-1"> + <stop + id="stop4755-60" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-3" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-3" /> + <stop + id="stop4757-6" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(82.156624,-30.356622)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-22" + xlink:href="#linearGradient4753-1" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-6" + id="linearGradient4737-32" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-6"> + <stop + id="stop4755-05" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-4" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-96" /> + <stop + id="stop4757-082" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(98.586578,-36.309505)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-74" + xlink:href="#linearGradient4753-6" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-01" + id="linearGradient4737-76" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-01"> + <stop + id="stop4755-2" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-93" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-8" /> + <stop + id="stop4757-5" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(115.01653,-42.262386)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-1" + xlink:href="#linearGradient4753-01" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-68" + id="linearGradient4737-6" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-68"> + <stop + id="stop4755-89" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-8" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-7" /> + <stop + id="stop4757-07" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(131.20837,-48.215268)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-9" + xlink:href="#linearGradient4753-68" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-39" + id="linearGradient4737-86" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-39"> + <stop + id="stop4755-4" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-53" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-82" /> + <stop + id="stop4757-3" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(147.40021,-54.16815)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-94" + xlink:href="#linearGradient4753-39" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-32" + id="linearGradient4737-1" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-32"> + <stop + id="stop4755-81" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-64" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-67" /> + <stop + id="stop4757-79" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(164.06828,-60.359147)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-6" + xlink:href="#linearGradient4753-32" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-2" + id="linearGradient4737-19" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-2"> + <stop + id="stop4755-63" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-1" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-5" /> + <stop + id="stop4757-9" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(180.49823,-66.073913)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-70" + xlink:href="#linearGradient4753-2" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-7" + id="linearGradient4737-61" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-7"> + <stop + id="stop4755-62" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-534" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-07" /> + <stop + id="stop4757-55" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(196.45195,-72.264911)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-3" + xlink:href="#linearGradient4753-7" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-017" + id="linearGradient4737-88" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-017"> + <stop + id="stop4755-5" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-0" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-59" /> + <stop + id="stop4757-09" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(213.12002,-77.979677)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-35" + xlink:href="#linearGradient4753-017" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-67" + id="linearGradient4737-72" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-67"> + <stop + id="stop4755-22" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-01" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-17" /> + <stop + id="stop4757-59" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(229.54998,-83.932557)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-18" + xlink:href="#linearGradient4753-67" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-99" + id="linearGradient4737-866" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + id="linearGradient4753-99"> + <stop + id="stop4755-26" + offset="0" + style="stop-color:#101010;stop-opacity:1;" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.47657159" + id="stop4761-65" /> + <stop + style="stop-color:#acacac;stop-opacity:1;" + offset="0.60369939" + id="stop4759-84" /> + <stop + id="stop4757-03" + offset="1" + style="stop-color:#3e3e3e;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="713.91241" + x2="447.14349" + y1="762.51996" + x1="462.33984" + gradientTransform="translate(245.97993,-89.885443)" + gradientUnits="userSpaceOnUse" + id="linearGradient4835-78" + xlink:href="#linearGradient4753-99" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753" + id="linearGradient5170" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.11034178,-0.45120379)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-09" + id="linearGradient5172" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(16.293772,-6.7832111)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-07" + id="linearGradient5174" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(32.866764,-12.497978)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-9" + id="linearGradient5176" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(49.296717,-18.212744)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-3" + id="linearGradient5178" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(65.72667,-24.403741)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-1" + id="linearGradient5180" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(82.156624,-30.356622)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-6" + id="linearGradient5182" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(98.586578,-36.309505)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-01" + id="linearGradient5184" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(115.01653,-42.262386)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-68" + id="linearGradient5186" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(131.20837,-48.215268)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-39" + id="linearGradient5188" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(147.40021,-54.16815)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-32" + id="linearGradient5190" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(164.06828,-60.359147)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-2" + id="linearGradient5192" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(180.49823,-66.073913)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-7" + id="linearGradient5194" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(196.45195,-72.264911)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-017" + id="linearGradient5196" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(213.12002,-77.979677)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-67" + id="linearGradient5198" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(229.54998,-83.932557)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4753-99" + id="linearGradient5200" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(245.97993,-89.885443)" + x1="462.33984" + y1="762.51996" + x2="447.14349" + y2="713.91241" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5205" + id="linearGradient5211" + x1="192.18854" + y1="640.29102" + x2="183.33424" + y2="664.34637" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5215" + id="linearGradient5221" + x1="550.91754" + y1="631.59814" + x2="562.11096" + y2="661.61688" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-53" + id="linearGradient5224" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(262.50578,95.187841)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-38" + id="linearGradient5227" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(246.07582,88.996844)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-0" + id="linearGradient5230" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(229.16964,83.996424)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-57" + id="linearGradient5233" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(213.21591,77.805426)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-42" + id="linearGradient5236" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(197.02408,71.376314)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-29" + id="linearGradient5239" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(180.59412,65.899662)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-62" + id="linearGradient5242" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(164.16417,59.708666)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-5" + id="linearGradient5245" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(147.4961,53.755784)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-63" + id="linearGradient5248" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(131.54238,47.802902)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-6" + id="linearGradient5251" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(114.39808,42.088135)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-7" + id="linearGradient5254" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(97.968123,36.373369)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-3" + id="linearGradient5257" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(82.014399,30.420488)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-4" + id="linearGradient5260" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(65.584446,24.229491)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-9" + id="linearGradient5263" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(49.154493,18.038493)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-2" + id="linearGradient5266" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(32.962654,12.085612)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249" + id="linearGradient5269" + gradientUnits="userSpaceOnUse" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" + gradientTransform="translate(16.500546,6.0614254)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249" + id="linearGradient5321" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(16.500546,6.0614254)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-2" + id="linearGradient5323" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(32.962654,12.085612)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-9" + id="linearGradient5325" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(49.154493,18.038493)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-4" + id="linearGradient5327" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(65.584446,24.229491)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-3" + id="linearGradient5329" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(82.014399,30.420488)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-7" + id="linearGradient5331" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(97.968123,36.373369)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-6" + id="linearGradient5333" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(114.39808,42.088135)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-63" + id="linearGradient5335" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(131.54238,47.802902)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-5" + id="linearGradient5337" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(147.4961,53.755784)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-62" + id="linearGradient5339" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(164.16417,59.708666)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-29" + id="linearGradient5341" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(180.59412,65.899662)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-42" + id="linearGradient5343" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(197.02408,71.376314)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-57" + id="linearGradient5345" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(213.21591,77.805426)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-0" + id="linearGradient5347" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(229.16964,83.996424)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-38" + id="linearGradient5349" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(246.07582,88.996844)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4249-53" + id="linearGradient5351" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(262.50578,95.187841)" + x1="56.430466" + y1="632.71771" + x2="67.791367" + y2="650.30981" /> </defs> <metadata id="metadata7"> @@ -373,7 +2243,7 @@ <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title /> + <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata> @@ -693,6 +2563,12 @@ d="m 197.35296,637.05028 26.22631,-36.06117 193.41902,1.96697 -36.06117,45.24038 -89.82511,-9.83486 7.21224,-15.08013 -43.27341,3.93395 z" id="path5039" inkscape:connector-curvature="0" /> + <path + style="fill:#ffffff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" + d="m 344.52579,102.27483 15.42653,-40.280383 23.99682,-15.426528 17.14059,9.427323 3.42812,11.998411 28.28197,-6.856235 14.56949,21.425734 0.85703,38.566318 -13.71247,30.85306 -21.42573,9.42732 -20.5687,-12.85544 -20.56871,8.57029 -24.98883,-23.71207 z" + id="path3253" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccccccc" /> </g> <g inkscape:groupmode="layer" @@ -730,176 +2606,191 @@ inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccccccccccscccccccccccccccscsccsscccsccccscsccscccccsscssscsssscsscscssscssssscssscscccsssscscccccsccssccssssscccccccccccccccccccccccsccssscsscccsssccsscsccscccccccsscssccssccsssccssccccccsssscsssscssssccscscsccscscscsccsscsccscccccccccccccccccccccccccccssccssccscssccssscccccccccccccscsssscssssscsscsssssssscsccssccscccccsssssssssccscc" /> <path - d="m 751.29906,574.49054 0,56.09559 -368.04049,133.95574 -368.040477,-133.95574 0,-56.61975 368.347517,133.55687 z" + d="m 749.69878,574.66835 0,56.09559 -366.44021,133.77793 -367.263011,-133.80025 0,-56.61975 367.570051,133.40138 z" id="path3354-4" style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccc" /> <g - transform="translate(0.11034178,-0.45120379)" - id="g5049-2" - style="stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"> + id="g5271" + transform="translate(-18.659191,-7.4636765)"> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3290-8" - d="m 321.48422,721.5392 -22.36609,12.913 0,30.0333" /> + style="fill:none;stroke:url(#linearGradient5321);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path3292-8" + d="m 92.180672,637.64386 -22.366085,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3292-8" - d="m 75.569784,632.03363 -22.366085,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5323);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-4" + d="m 108.64278,643.66805 -22.366085,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3294-1" - d="m 305.08992,715.57213 -22.36608,12.91307 0,30.0333" /> + style="fill:none;stroke:url(#linearGradient5325);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-5" + d="m 124.83462,649.62094 -22.36609,12.91306 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3296-8" - d="m 288.69563,709.6051 -22.36609,12.9131 0,30.0332" /> + style="fill:none;stroke:url(#linearGradient5327);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-0" + d="m 141.26457,655.81193 -22.36608,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3298-6" - d="m 272.30133,703.63806 -22.36608,12.91304 0,30.0333" /> + style="fill:none;stroke:url(#linearGradient5329);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-9" + d="m 157.69453,662.00293 -22.36608,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3300-0" - d="m 255.90704,697.67102 -22.36609,12.91307 0,30.03331" /> + style="fill:none;stroke:url(#linearGradient5331);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-7" + d="m 173.64825,667.9558 -22.36608,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3302-2" - d="m 239.51274,691.70399 -22.36608,12.91306 0,30.03325" /> + style="fill:none;stroke:url(#linearGradient5333);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-41" + d="m 190.07821,673.67057 -22.36608,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3304-4" - d="m 223.11845,685.73695 -22.36609,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5335);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-2" + d="m 207.22251,679.38534 -22.36609,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3306-9" - d="m 206.72415,679.76992 -22.36609,12.91306 0,30.03332" /> + style="fill:none;stroke:url(#linearGradient5337);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-21" + d="m 223.17623,685.33822 -22.36609,12.91306 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3308-0" - d="m 190.32985,673.80288 -22.36608,12.91307 0,30.03325" /> + style="fill:none;stroke:url(#linearGradient5339);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-6" + d="m 239.8443,691.2911 -22.36609,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3310-2" - d="m 173.93556,667.83585 -22.36609,12.91306 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5341);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-59" + d="m 256.27425,697.4821 -22.36609,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3312-2" - d="m 157.54126,661.86881 -22.36608,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5343);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-1" + d="m 272.70421,702.95875 -22.36609,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3314-1" - d="m 141.14697,655.90177 -22.36609,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5345);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-42" + d="m 288.89604,709.38786 -22.36609,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3316-5" - d="m 124.75267,649.93474 -22.36608,12.91306 0,30.03329" /> + style="fill:none;stroke:url(#linearGradient5347);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-73" + d="m 304.84977,715.57886 -22.36609,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3318-4" - d="m 108.35837,643.9677 -22.36608,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5349);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-72" + d="m 321.75595,720.57928 -22.36609,12.91307 0,30.03328" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3320-4" - d="m 91.96408,638.00067 -22.366085,12.91306 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5351);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3292-8-3" + d="m 338.18591,726.77028 -22.36609,12.91307 0,30.03328" /> + </g> + <g + id="g5152" + transform="translate(16.429953,-5.9528819)"> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + style="fill:none;stroke:url(#linearGradient5170);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" id="path3322-4" - d="m 443.61027,721.5392 22.36608,12.913 0,30.0333" /> + d="m 443.72061,721.088 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3324-2" - d="m 476.39886,709.6051 22.36608,12.9131 0,30.0332" /> + style="fill:none;stroke:url(#linearGradient5172);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-3" + d="m 459.90404,714.75598 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3326-5" - d="m 460.00456,715.57213 22.36609,12.91307 0,30.0333" /> + style="fill:none;stroke:url(#linearGradient5174);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-9" + d="m 476.47704,709.04122 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3328-0" - d="m 525.58175,691.70399 22.36608,12.91306 0,30.03325" /> + style="fill:none;stroke:url(#linearGradient5176);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-8" + d="m 492.90699,703.32646 22.36607,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3330-4" - d="m 509.18745,697.67102 22.36609,12.91307 0,30.03331" /> + style="fill:none;stroke:url(#linearGradient5178);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-1" + d="m 509.33694,697.13546 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3332-2" - d="m 492.79316,703.63806 22.36608,12.91304 0,30.0333" /> + style="fill:none;stroke:url(#linearGradient5180);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-14" + d="m 525.76689,691.18258 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3334-1" - d="m 558.37034,679.76992 22.36608,12.91306 0,30.03332" /> + style="fill:none;stroke:url(#linearGradient5182);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-0" + d="m 542.19685,685.22969 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3336-2" - d="m 541.97604,685.73695 22.36609,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5184);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-5" + d="m 558.6268,679.27682 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3338-7" - d="m 607.55322,661.86881 22.36609,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5186);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-15" + d="m 574.81864,673.32393 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3340-7" - d="m 574.76463,673.80288 22.36609,12.91307 0,30.03325" /> + style="fill:none;stroke:url(#linearGradient5188);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-85" + d="m 591.01048,667.37105 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3342-9" - d="m 591.15893,667.83585 22.36609,12.91306 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5190);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-4" + d="m 607.67855,661.18005 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3344-5" - d="m 689.5247,632.03363 22.36609,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5192);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-2" + d="m 624.1085,655.46528 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3346-5" - d="m 623.94752,655.90177 22.36609,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5194);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-18" + d="m 640.06222,649.27429 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3348-4" - d="m 640.34182,649.93474 22.36608,12.91306 0,30.03329" /> + style="fill:none;stroke:url(#linearGradient5196);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-42" + d="m 656.73029,643.55953 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3350-0" - d="m 656.73611,643.9677 22.36609,12.91307 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5198);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-17" + d="m 673.16025,637.60664 22.36608,12.913 0,30.0333" /> <path inkscape:connector-curvature="0" - style="fill:none;stroke:#3e3e3e;stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" - id="path3352-3" - d="m 673.13041,638.00067 22.36608,12.91306 0,30.03328" /> + style="fill:none;stroke:url(#linearGradient5200);stroke-width:9.60000038;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" + id="path3322-4-31" + d="m 689.5902,631.65376 22.36608,12.913 0,30.0333" /> </g> + <path + style="fill:url(#linearGradient5211);fill-opacity:1;stroke:none;display:inline" + d="m 13.872826,595.95429 c 0.387521,-16.26739 -3.132044,-24.34489 11.843623,-17.81444 67.361595,23.56741 305.258621,108.07438 347.099071,124.14652 6.9538,4.2814 16.05227,4.7547 12.47851,7.2194 -0.0902,3.98398 -2.69274,4.02033 -4.62883,4.99233 -1.93608,0.97199 -2.92965,-0.15731 -5.87591,0.39099 -1.28974,3.03308 -1.90493,21.91052 -1.90493,21.91052 0,0 -3.99564,-7.30146 -4.7623,-11.12968 -0.76666,-3.82822 -3.77724,-3.13603 -9.18147,-5.22972 C 289.67149,695.89705 13.872826,595.95429 13.872826,595.95429 z" + id="path5202" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccscczcc" /> + <path + style="fill:url(#linearGradient5221);fill-opacity:1;stroke:none" + d="m 749.01081,575.84113 c 0.30103,-3.12022 -1.0367,-3.0558 -13.718,-9.28068 -46.08067,16.93915 -285.08057,107.25201 -352.73995,131.17677 -26.94394,-4.90548 4.70243,5.27427 9.2182,8.05818 4.51572,2.78391 16.61463,-1.25017 26.77523,-5.28719 53.11696,-19.719 286.75703,-106.37669 330.46452,-124.66708 z" + id="path5213" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" /> </g> <g inkscape:groupmode="layer" diff --git a/py/builtin.c b/py/builtin.c index 078f4b49c3..04bb2681db 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -18,7 +18,7 @@ // args[0] is function from class body // args[1] is class name // args[2:] are base objects -mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) { assert(2 <= n_args); // we differ from CPython: we set the new __locals__ object here @@ -62,14 +62,16 @@ mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__); -mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { +static mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { if (o != mp_const_none) { - mp_obj_print(o); + mp_obj_print(o, PRINT_REPR); printf("\n"); } return mp_const_none; } +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print__); + mp_obj_t mp_builtin_abs(mp_obj_t o_in) { if (MP_OBJ_IS_SMALL_INT(o_in)) { mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in); @@ -97,7 +99,9 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) { } } -mp_obj_t mp_builtin_all(mp_obj_t o_in) { +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs); + +static mp_obj_t mp_builtin_all(mp_obj_t o_in) { mp_obj_t iterable = rt_getiter(o_in); mp_obj_t item; while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { @@ -108,7 +112,9 @@ mp_obj_t mp_builtin_all(mp_obj_t o_in) { return mp_const_true; } -mp_obj_t mp_builtin_any(mp_obj_t o_in) { +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all); + +static mp_obj_t mp_builtin_any(mp_obj_t o_in) { mp_obj_t iterable = rt_getiter(o_in); mp_obj_t item; while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { @@ -119,7 +125,9 @@ mp_obj_t mp_builtin_any(mp_obj_t o_in) { return mp_const_false; } -mp_obj_t mp_builtin_callable(mp_obj_t o_in) { +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any); + +static mp_obj_t mp_builtin_callable(mp_obj_t o_in) { if (mp_obj_is_callable(o_in)) { return mp_const_true; } else { @@ -127,19 +135,21 @@ mp_obj_t mp_builtin_callable(mp_obj_t o_in) { } } -mp_obj_t mp_builtin_chr(mp_obj_t o_in) { +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable); + +static mp_obj_t mp_builtin_chr(mp_obj_t o_in) { int ord = mp_obj_get_int(o_in); if (0 <= ord && ord <= 0x10ffff) { - char *str = m_new(char, 2); - str[0] = ord; - str[1] = '\0'; - return mp_obj_new_str(qstr_from_str_take(str, 2)); + char str[2] = {ord, '\0'}; + return mp_obj_new_str(qstr_from_strn_copy(str, 1)); } else { nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "chr() arg not in range(0x110000)")); } } -mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr); + +static mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) { mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in); mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in); @@ -152,6 +162,8 @@ mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { } } +MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod); + static mp_obj_t mp_builtin_hash(mp_obj_t o_in) { // TODO hash will generally overflow small integer; can we safely truncate it? return mp_obj_new_int(mp_obj_hash(o_in)); @@ -165,7 +177,7 @@ static mp_obj_t mp_builtin_iter(mp_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter); -mp_obj_t mp_builtin_len(mp_obj_t o_in) { +static mp_obj_t mp_builtin_len(mp_obj_t o_in) { mp_obj_t len = mp_obj_len_maybe(o_in); if (len == NULL) { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); @@ -174,7 +186,9 @@ mp_obj_t mp_builtin_len(mp_obj_t o_in) { } } -mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) { +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_builtin_len); + +static mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) { if (n_args == 1) { // given an iterable mp_obj_t iterable = rt_getiter(args[0]); @@ -201,7 +215,9 @@ mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) { } } -mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) { +MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_max_obj, 1, mp_builtin_max); + +static mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) { if (n_args == 1) { // given an iterable mp_obj_t iterable = rt_getiter(args[0]); @@ -228,6 +244,8 @@ mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) { } } +MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_min_obj, 1, mp_builtin_min); + static mp_obj_t mp_builtin_next(mp_obj_t o) { mp_obj_t ret = rt_iternext(o); if (ret == mp_const_stop_iteration) { @@ -239,7 +257,7 @@ static mp_obj_t mp_builtin_next(mp_obj_t o) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next); -mp_obj_t mp_builtin_ord(mp_obj_t o_in) { +static mp_obj_t mp_builtin_ord(mp_obj_t o_in) { const char *str = qstr_str(mp_obj_get_qstr(o_in)); if (strlen(str) == 1) { return mp_obj_new_int(str[0]); @@ -248,46 +266,56 @@ mp_obj_t mp_builtin_ord(mp_obj_t o_in) { } } -mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) { +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord); + +static mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) { + assert(2 <= n_args && n_args <= 3); switch (n_args) { case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]); - case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise... - default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "pow expected at most 3 arguments, got %d", n_args)); + default: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise... } } -mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args) { +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow); + +static mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args) { for (int i = 0; i < n_args; i++) { if (i > 0) { printf(" "); } - if (MP_OBJ_IS_TYPE(args[i], &str_type)) { - // special case, print string raw - printf("%s", qstr_str(mp_obj_str_get(args[i]))); - } else { - // print the object Python style - mp_obj_print(args[i]); - } + mp_obj_print(args[i], PRINT_STR); } printf("\n"); return mp_const_none; } -mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) { +MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_print_obj, 0, mp_builtin_print); + +static mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) { + assert(1 <= n_args && n_args <= 3); switch (n_args) { case 1: return mp_obj_new_range(0, mp_obj_get_int(args[0]), 1); case 2: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), 1); - case 3: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2])); - default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "range expected at most 3 arguments, got %d", n_args)); + default: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2])); } } -mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_range_obj, 1, 3, mp_builtin_range); + +static mp_obj_t mp_builtin_repr(mp_obj_t o_in) { + vstr_t *vstr = vstr_new(); + mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, vstr, o_in, PRINT_REPR); + return mp_obj_new_str(qstr_from_str_take(vstr->buf, vstr->alloc)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); + +static mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { + assert(1 <= n_args && n_args <= 2); mp_obj_t value; switch (n_args) { case 1: value = mp_obj_new_int(0); break; - case 2: value = args[1]; break; - default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "sum expected at most 2 arguments, got %d", n_args)); + default: value = args[1]; break; } mp_obj_t iterable = rt_getiter(args[0]); mp_obj_t item; @@ -296,3 +324,33 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { } return value; } + +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); + +static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) { + mp_obj_t *args_items = NULL; + uint args_len = 0; + + assert(MP_OBJ_IS_TYPE(args, &tuple_type)); + mp_obj_tuple_get(args, &args_len, &args_items); + assert(args_len >= 1); + if (args_len > 1) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, + "must use keyword argument for key function")); + } + mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, args_items); + mp_obj_t new_args = rt_build_tuple(1, &self); + mp_obj_list_sort(new_args, kwargs); + + return self; +} + +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted); + +static mp_obj_t mp_builtin_str(mp_obj_t o_in) { + vstr_t *vstr = vstr_new(); + mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, o_in, PRINT_STR); + return mp_obj_new_str(qstr_from_str_take(vstr->buf, vstr->alloc)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_str_obj, mp_builtin_str); diff --git a/py/builtin.h b/py/builtin.h index db7d517a06..f4038b47b4 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -1,25 +1,28 @@ -// TODO convert all these to objects using MP_DECLARE and MP_DEFINE +mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ(mp_builtin___build_class___obj); -mp_obj_t mp_builtin___import__(int n, mp_obj_t *args); -mp_obj_t mp_builtin___repl_print__(mp_obj_t o); -mp_obj_t mp_builtin_abs(mp_obj_t o_in); -mp_obj_t mp_builtin_all(mp_obj_t o_in); -mp_obj_t mp_builtin_any(mp_obj_t o_in); -mp_obj_t mp_builtin_callable(mp_obj_t o_in); -mp_obj_t mp_builtin_chr(mp_obj_t o_in); -mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin___repl_print___obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_eval_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_isinstance_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_issubclass_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_iter_obj); -mp_obj_t mp_builtin_len(mp_obj_t o_in); -mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args); -mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args); -mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_len_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_list_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_max_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_min_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_next_obj); -mp_obj_t mp_builtin_ord(mp_obj_t o_in); -mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args); -mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args); -mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args); -mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_ord_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_pow_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_print_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_range_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_str_obj); diff --git a/py/builtineval.c b/py/builtineval.c new file mode 100644 index 0000000000..a8a7a476a3 --- /dev/null +++ b/py/builtineval.c @@ -0,0 +1,50 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "lexer.h" +#include "lexerunix.h" +#include "parse.h" +#include "obj.h" +#include "compile.h" +#include "runtime0.h" +#include "runtime.h" +#include "map.h" +#include "builtin.h" + +static mp_obj_t mp_builtin_eval(mp_obj_t o_in) { + const char *str = qstr_str(mp_obj_get_qstr(o_in)); + + // create the lexer + mp_lexer_t *lex = mp_lexer_new_from_str_len("<string>", str, strlen(str), 0); + + // parse the string + qstr parse_exc_id; + const char *parse_exc_msg; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_EVAL_INPUT, &parse_exc_id, &parse_exc_msg); + mp_lexer_free(lex); + + if (pn == MP_PARSE_NODE_NULL) { + // parse error; raise exception + nlr_jump(mp_obj_new_exception_msg(parse_exc_id, parse_exc_msg)); + } + + // compile the string + mp_obj_t module_fun = mp_compile(pn, false); + + if (module_fun == mp_const_none) { + // TODO handle compile error correctly + return mp_const_none; + } + + // complied successfully, execute it + return rt_call_function_0(module_fun); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_eval_obj, mp_builtin_eval); diff --git a/py/builtinimport.c b/py/builtinimport.c index 90a0fc3394..2eca36fbc6 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -18,7 +18,7 @@ #include "map.h" #include "builtin.h" -mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) { +mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { /* printf("import:\n"); for (int i = 0; i < n; i++) { @@ -48,16 +48,19 @@ mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) { rt_globals_set(mp_obj_module_get_globals(module_obj)); // parse the imported script - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); + qstr parse_exc_id; + const char *parse_exc_msg; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); mp_lexer_free(lex); if (pn == MP_PARSE_NODE_NULL) { - // TODO handle parse error correctly + // parse error; clean up and raise exception rt_locals_set(old_locals); rt_globals_set(old_globals); - return mp_const_none; + nlr_jump(mp_obj_new_exception_msg(parse_exc_id, parse_exc_msg)); } + // compile the imported script mp_obj_t module_fun = mp_compile(pn, false); if (module_fun == mp_const_none) { diff --git a/py/compile.c b/py/compile.c index 2e22d64262..b24e94a8dc 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1316,7 +1316,7 @@ void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { int l_end = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], true, l_end); - EMIT(load_id, MP_QSTR_AssertionError); + EMIT(load_global, MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { // assertion message compile_node(comp, pns->nodes[1]); @@ -2708,7 +2708,12 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { #endif // compile - if (scope->kind == SCOPE_MODULE) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) { + assert(scope->kind == SCOPE_MODULE); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; + compile_node(comp, pns->nodes[0]); // compile the expression + EMIT(return_value); + } else if (scope->kind == SCOPE_MODULE) { if (!comp->is_repl) { check_for_doc_string(comp, scope->pn); } @@ -2833,7 +2838,6 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } EMIT(end_pass); - } void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) { diff --git a/py/emitpass1.c b/py/emitpass1.c index 2f0ecac86d..60fdd0b825 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -45,10 +45,7 @@ static void emit_pass1_load_id(emit_t *emit, qstr qstr) { bool added; id_info_t *id = scope_find_or_add_id(emit->scope, qstr, &added); if (added) { - if (qstr == MP_QSTR_AssertionError) { - // TODO how much of a hack is this? - id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; - } else if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) { + if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) { // special case, super is a global, and also counts as use of __class__ id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; id_info_t *id2 = scope_find_local_in_parent(emit->scope, emit->qstr___class__); @@ -8,15 +8,8 @@ #if MICROPY_ENABLE_GC -// a machine word is big enough to hold a pointer -/* -#define BYTES_PER_WORD (8) -typedef unsigned long machine_uint_t; -*/ typedef unsigned char byte; -#define BITS_PER_BYTE (8) -#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD) #define WORDS_PER_BLOCK (4) #define BYTES_PER_BLOCK (WORDS_PER_BLOCK * BYTES_PER_WORD) #define STACK_SIZE (64) // tunable; minimum is 1 diff --git a/py/grammar.h b/py/grammar.h index 4d53bd3fc4..32be6c66ca 100644 --- a/py/grammar.h +++ b/py/grammar.h @@ -15,6 +15,8 @@ DEF_RULE(single_input, nc, or(3), tok(NEWLINE), rule(simple_stmt), rule(compound DEF_RULE(file_input, nc, and(1), opt_rule(file_input_2)) DEF_RULE(file_input_2, c(generic_all_nodes), one_or_more, rule(file_input_3)) DEF_RULE(file_input_3, nc, or(2), tok(NEWLINE), rule(stmt)) +DEF_RULE(eval_input, nc, and(2), rule(testlist), opt_rule(eval_input_2)) +DEF_RULE(eval_input_2, nc, and(1), tok(NEWLINE)) // decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE // decorators: decorator+ diff --git a/py/lexer.c b/py/lexer.c index d4205236c3..6feb231e0c 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -35,6 +35,7 @@ struct _mp_lexer_t { mp_token_t tok_cur; }; +// TODO replace with a call to a standard function bool str_strn_equal(const char *str, const char *strn, int len) { uint i = 0; @@ -66,15 +67,6 @@ void mp_token_show(const mp_token_t *tok) { printf("\n"); } -void mp_token_show_error_prefix(const mp_token_t *tok) { - printf("(%s:%d:%d) ", tok->src_name, tok->src_line, tok->src_column); -} - -bool mp_token_show_error(const mp_token_t *tok, const char *msg) { - printf("(%s:%d:%d) %s\n", tok->src_name, tok->src_line, tok->src_column, msg); - return false; -} - #define CUR_CHAR(lex) ((lex)->chr0) static bool is_end(mp_lexer_t *lex) { @@ -299,8 +291,15 @@ static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs // backslash (outside string literals) must appear just before a physical newline next_char(lex); if (!is_physical_newline(lex)) { - // TODO SyntaxError - assert(0); + // SyntaxError: unexpected character after line continuation character + tok->src_name = lex->name; + tok->src_line = lex->line; + tok->src_column = lex->column; + tok->kind = MP_TOKEN_BAD_LINE_CONTINUATION; + vstr_reset(&lex->vstr); + tok->str = vstr_str(&lex->vstr); + tok->len = 0; + return; } else { next_char(lex); } @@ -607,7 +606,7 @@ mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_strea lex->num_indent_level = 1; lex->indent_level = m_new(uint16_t, lex->alloc_indent_level); lex->indent_level[0] = 0; - vstr_init(&lex->vstr); + vstr_init(&lex->vstr, 32); // preload characters lex->chr0 = stream_next_char(stream_data); @@ -677,8 +676,9 @@ bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str) { } */ -bool mp_lexer_show_error(mp_lexer_t *lex, const char *msg) { - return mp_token_show_error(&lex->tok_cur, msg); +bool mp_lexer_show_error_pythonic_prefix(mp_lexer_t *lex) { + printf(" File \"%s\", line %d column %d\n", lex->tok_cur.src_name, lex->tok_cur.src_line, lex->tok_cur.src_column); + return false; } bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg) { diff --git a/py/lexer.h b/py/lexer.h index 9dfcb128c5..ea928c77f8 100644 --- a/py/lexer.h +++ b/py/lexer.h @@ -10,19 +10,20 @@ typedef enum _mp_token_kind_t { MP_TOKEN_INVALID, MP_TOKEN_DEDENT_MISMATCH, MP_TOKEN_LONELY_STRING_OPEN, + MP_TOKEN_BAD_LINE_CONTINUATION, - MP_TOKEN_NEWLINE, // 4 - MP_TOKEN_INDENT, // 5 - MP_TOKEN_DEDENT, // 6 + MP_TOKEN_NEWLINE, // 5 + MP_TOKEN_INDENT, // 6 + MP_TOKEN_DEDENT, // 7 - MP_TOKEN_NAME, // 7 + MP_TOKEN_NAME, // 8 MP_TOKEN_NUMBER, MP_TOKEN_STRING, MP_TOKEN_BYTES, MP_TOKEN_ELLIPSIS, - MP_TOKEN_KW_FALSE, // 12 + MP_TOKEN_KW_FALSE, // 13 MP_TOKEN_KW_NONE, MP_TOKEN_KW_TRUE, MP_TOKEN_KW_AND, @@ -31,7 +32,7 @@ typedef enum _mp_token_kind_t { MP_TOKEN_KW_BREAK, MP_TOKEN_KW_CLASS, MP_TOKEN_KW_CONTINUE, - MP_TOKEN_KW_DEF, // 21 + MP_TOKEN_KW_DEF, // 22 MP_TOKEN_KW_DEL, MP_TOKEN_KW_ELIF, MP_TOKEN_KW_ELSE, @@ -41,7 +42,7 @@ typedef enum _mp_token_kind_t { MP_TOKEN_KW_FROM, MP_TOKEN_KW_GLOBAL, MP_TOKEN_KW_IF, - MP_TOKEN_KW_IMPORT, // 31 + MP_TOKEN_KW_IMPORT, // 32 MP_TOKEN_KW_IN, MP_TOKEN_KW_IS, MP_TOKEN_KW_LAMBDA, @@ -51,12 +52,12 @@ typedef enum _mp_token_kind_t { MP_TOKEN_KW_PASS, MP_TOKEN_KW_RAISE, MP_TOKEN_KW_RETURN, - MP_TOKEN_KW_TRY, // 41 + MP_TOKEN_KW_TRY, // 42 MP_TOKEN_KW_WHILE, MP_TOKEN_KW_WITH, MP_TOKEN_KW_YIELD, - MP_TOKEN_OP_PLUS, // 45 + MP_TOKEN_OP_PLUS, // 46 MP_TOKEN_OP_MINUS, MP_TOKEN_OP_STAR, MP_TOKEN_OP_DBL_STAR, @@ -66,7 +67,7 @@ typedef enum _mp_token_kind_t { MP_TOKEN_OP_LESS, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_OP_MORE, - MP_TOKEN_OP_DBL_MORE, // 55 + MP_TOKEN_OP_DBL_MORE, // 56 MP_TOKEN_OP_AMPERSAND, MP_TOKEN_OP_PIPE, MP_TOKEN_OP_CARET, @@ -76,7 +77,7 @@ typedef enum _mp_token_kind_t { MP_TOKEN_OP_DBL_EQUAL, MP_TOKEN_OP_NOT_EQUAL, - MP_TOKEN_DEL_PAREN_OPEN, // 64 + MP_TOKEN_DEL_PAREN_OPEN, // 65 MP_TOKEN_DEL_PAREN_CLOSE, MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE, @@ -86,7 +87,7 @@ typedef enum _mp_token_kind_t { MP_TOKEN_DEL_COLON, MP_TOKEN_DEL_PERIOD, MP_TOKEN_DEL_SEMICOLON, - MP_TOKEN_DEL_AT, // 74 + MP_TOKEN_DEL_AT, // 75 MP_TOKEN_DEL_EQUAL, MP_TOKEN_DEL_PLUS_EQUAL, MP_TOKEN_DEL_MINUS_EQUAL, @@ -96,7 +97,7 @@ typedef enum _mp_token_kind_t { MP_TOKEN_DEL_PERCENT_EQUAL, MP_TOKEN_DEL_AMPERSAND_EQUAL, MP_TOKEN_DEL_PIPE_EQUAL, - MP_TOKEN_DEL_CARET_EQUAL, // 84 + MP_TOKEN_DEL_CARET_EQUAL, // 85 MP_TOKEN_DEL_DBL_MORE_EQUAL, MP_TOKEN_DEL_DBL_LESS_EQUAL, MP_TOKEN_DEL_DBL_STAR_EQUAL, @@ -123,8 +124,6 @@ typedef void (*mp_lexer_stream_close_t)(void*); typedef struct _mp_lexer_t mp_lexer_t; void mp_token_show(const mp_token_t *tok); -void mp_token_show_error_prefix(const mp_token_t *tok); -bool mp_token_show_error(const mp_token_t *tok, const char *msg); mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close); mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, uint free_len); @@ -133,12 +132,8 @@ void mp_lexer_free(mp_lexer_t *lex); void mp_lexer_to_next(mp_lexer_t *lex); const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex); bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind); -/* unused -bool mp_lexer_is_str(mp_lexer_t *lex, const char *str); -bool mp_lexer_opt_kind(mp_lexer_t *lex, mp_token_kind_t kind); -bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str); -*/ -bool mp_lexer_show_error(mp_lexer_t *lex, const char *msg); + +bool mp_lexer_show_error_pythonic_prefix(mp_lexer_t *lex); bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg); // used to import a module; must be implemented for a specific port @@ -132,28 +132,45 @@ void mp_set_init(mp_set_t *set, int n) { set->table = m_new0(mp_obj_t, set->alloc); } -mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) { - int hash = mp_obj_hash(index); - assert(set->alloc); /* FIXME: if alloc is ever 0 when doing a lookup, this'll fail: */ - int pos = hash % set->alloc; +static void mp_set_rehash(mp_set_t *set) { + int old_alloc = set->alloc; + mp_obj_t *old_table = set->table; + set->alloc = get_doubling_prime_greater_or_equal_to(set->alloc + 1); + set->used = 0; + set->table = m_new0(mp_obj_t, set->alloc); + for (int i = 0; i < old_alloc; i++) { + if (old_table[i] != NULL) { + mp_set_lookup(set, old_table[i], true); + } + } + m_del(mp_obj_t, old_table, old_alloc); +} + +mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) { + int hash; + int pos; + if (set->alloc == 0) { + if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { + mp_set_rehash(set); + } else { + return NULL; + } + } + if (lookup_kind & MP_MAP_LOOKUP_FIRST) { + hash = 0; + pos = 0; + } else { + hash = mp_obj_hash(index);; + pos = hash % set->alloc; + } for (;;) { mp_obj_t elem = set->table[pos]; if (elem == MP_OBJ_NULL) { // not in table - if (add_if_not_found) { + if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) { if (set->used + 1 >= set->alloc) { // not enough room in table, rehash it - int old_alloc = set->alloc; - mp_obj_t *old_table = set->table; - set->alloc = get_doubling_prime_greater_or_equal_to(set->alloc + 1); - set->used = 0; - set->table = m_new(mp_obj_t, set->alloc); - for (int i = 0; i < old_alloc; i++) { - if (old_table[i] != NULL) { - mp_set_lookup(set, old_table[i], true); - } - } - m_del(mp_obj_t, old_table, old_alloc); + mp_set_rehash(set); // restart the search for the new element pos = hash % set->alloc; } else { @@ -161,11 +178,17 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) { set->table[pos] = index; return index; } + } else if (lookup_kind & MP_MAP_LOOKUP_FIRST) { + pos++; } else { return MP_OBJ_NULL; } - } else if (mp_obj_equal(elem, index)) { + } else if (lookup_kind & MP_MAP_LOOKUP_FIRST || mp_obj_equal(elem, index)) { // found it + if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND) { + set->used--; + set->table[pos] = NULL; + } return elem; } else { // not yet found, keep searching in this table @@ -173,3 +196,13 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) { } } } + +void mp_set_clear(mp_set_t *set) { + set->used = 0; + machine_uint_t a = set->alloc; + set->alloc = 0; + set->table = m_renew(mp_obj_t, set->table, a, set->alloc); + for (uint i=0; i<set->alloc; i++) { + set->table[i] = NULL; + } +} @@ -19,9 +19,10 @@ typedef struct _mp_set_t { } mp_set_t; typedef enum _mp_map_lookup_kind_t { - MP_MAP_LOOKUP, - MP_MAP_LOOKUP_ADD_IF_NOT_FOUND, - MP_MAP_LOOKUP_REMOVE_IF_FOUND, + MP_MAP_LOOKUP, // 0 + MP_MAP_LOOKUP_ADD_IF_NOT_FOUND, // 1 + MP_MAP_LOOKUP_REMOVE_IF_FOUND, // 2 + MP_MAP_LOOKUP_FIRST = 4, } mp_map_lookup_kind_t; int get_doubling_prime_greater_or_equal_to(int x); @@ -31,4 +32,5 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t void mp_map_clear(mp_map_t *map); void mp_set_init(mp_set_t *set, int n); -mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found); +mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind); +void mp_set_clear(mp_set_t *set); @@ -21,6 +21,7 @@ typedef unsigned int uint; #define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) #define m_del(type, ptr, num) m_free(ptr, sizeof(type) * (num)) #define m_del_obj(type, ptr) (m_del(type, ptr, 1)) +#define m_del_var(obj_type, var_type, var_num, ptr) (m_free(ptr, sizeof(obj_type) + sizeof(var_type) * (var_num))) void *m_malloc(int num_bytes); void *m_malloc0(int num_bytes); @@ -49,6 +50,8 @@ bool unichar_isdigit(unichar c); #define streq(s1, s2) (strcmp((s1), (s2)) == 0) */ +long strtonum(const char *restrict s, int base); + /** variable string *********************************************/ typedef struct _vstr_t { @@ -58,15 +61,19 @@ typedef struct _vstr_t { bool had_error; } vstr_t; -void vstr_init(vstr_t *vstr); +void vstr_init(vstr_t *vstr, int alloc); void vstr_clear(vstr_t *vstr); vstr_t *vstr_new(void); +vstr_t *vstr_new_size(int alloc); void vstr_free(vstr_t *vstr); void vstr_reset(vstr_t *vstr); bool vstr_had_error(vstr_t *vstr); char *vstr_str(vstr_t *vstr); int vstr_len(vstr_t *vstr); void vstr_hint_size(vstr_t *vstr, int size); +char *vstr_extend(vstr_t *vstr, int size); +bool vstr_set_size(vstr_t *vstr, int size); +bool vstr_shrink(vstr_t *vstr); char *vstr_add_len(vstr_t *vstr, int len); void vstr_add_byte(vstr_t *vstr, byte v); void vstr_add_char(vstr_t *vstr, unichar chr); diff --git a/py/mpconfig.h b/py/mpconfig.h index 2017ba366a..5d8c57692e 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -62,6 +62,18 @@ #define MICROPY_ENABLE_LEXER_UNIX (0) #endif +// Long int implementation +#define MICROPY_LONGINT_IMPL_NONE (0) +#define MICROPY_LONGINT_IMPL_LONGLONG (1) + +#ifndef MICROPY_LONGINT_IMPL +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) +#endif + +#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG +typedef long long mp_longint_impl_t; +#endif + // Whether to support float and complex types #ifndef MICROPY_ENABLE_FLOAT #define MICROPY_ENABLE_FLOAT (0) @@ -76,6 +88,11 @@ /*****************************************************************************/ /* Miscellaneous settings */ +#define BITS_PER_BYTE (8) +#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD) +// machine_int_t value with most significant bit set +#define WORD_MSBIT_HIGH (((machine_uint_t)1) << (BYTES_PER_WORD * 8 - 1)) + // printf format spec to use for machine_int_t and friends #ifndef INT_FMT #ifdef __LP64__ diff --git a/py/mpqstrraw.h b/py/mpqstrraw.h index e4404a36f0..6674a2c398 100644 --- a/py/mpqstrraw.h +++ b/py/mpqstrraw.h @@ -24,13 +24,14 @@ Q(StopIteration) Q(AssertionError) Q(AttributeError) +Q(IndentationError) Q(IndexError) Q(KeyError) Q(NameError) +Q(OSError) Q(SyntaxError) Q(TypeError) Q(ValueError) -Q(OSError) Q(abs) Q(all) @@ -41,6 +42,9 @@ Q(chr) Q(complex) Q(dict) Q(divmod) +Q(enumerate) +Q(eval) +Q(filter) Q(float) Q(hash) Q(int) @@ -49,6 +53,7 @@ Q(issubclass) Q(iter) Q(len) Q(list) +Q(map) Q(max) Q(min) Q(next) @@ -56,10 +61,14 @@ Q(ord) Q(pow) Q(print) Q(range) +Q(repr) Q(set) +Q(sorted) Q(sum) +Q(str) Q(tuple) Q(type) +Q(zip) Q(append) Q(pop) @@ -13,7 +13,6 @@ #include "runtime0.h" #include "runtime.h" #include "map.h" -#include "strtonum.h" mp_obj_t mp_obj_get_type(mp_obj_t o_in) { if (MP_OBJ_IS_SMALL_INT(o_in)) { @@ -42,21 +41,21 @@ void printf_wrapper(void *env, const char *fmt, ...) { va_end(args); } -void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { +void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { if (MP_OBJ_IS_SMALL_INT(o_in)) { print(env, "%d", (int)MP_OBJ_SMALL_INT_VALUE(o_in)); } else { mp_obj_base_t *o = o_in; if (o->type->print != NULL) { - o->type->print(print, env, o_in); + o->type->print(print, env, o_in, kind); } else { print(env, "<%s>", o->type->name); } } } -void mp_obj_print(mp_obj_t o_in) { - mp_obj_print_helper(printf_wrapper, NULL, o_in); +void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) { + mp_obj_print_helper(printf_wrapper, NULL, o_in, kind); } bool mp_obj_is_callable(mp_obj_t o_in) { @@ -109,15 +108,28 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { return val == 0; } else if (o2 == mp_const_true) { return val == 1; - } else { - return false; + } else if (MP_OBJ_IS_TYPE(o2, &int_type)) { + // If o2 is long int, dispatch to its virtual methods + mp_obj_base_t *o = o2; + if (o->type->binary_op != NULL) { + mp_obj_t r = o->type->binary_op(RT_COMPARE_OP_EQUAL, o2, o1); + return r == mp_const_true ? true : false; + } } + return false; } } else if (MP_OBJ_IS_QSTR(o1) || MP_OBJ_IS_QSTR(o2)) { return false; } else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) { return mp_obj_str_get(o1) == mp_obj_str_get(o2); } else { + mp_obj_base_t *o = o1; + if (o->type->binary_op != NULL) { + mp_obj_t r = o->type->binary_op(RT_COMPARE_OP_EQUAL, o1, o2); + if (r != MP_OBJ_NULL) { + return r == mp_const_true ? true : false; + } + } // TODO: Debugging helper printf("Equality for '%s' and '%s' types not yet implemented\n", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2)); assert(0); @@ -137,12 +149,6 @@ bool mp_obj_less(mp_obj_t o1, mp_obj_t o2) { } machine_int_t mp_obj_get_int(mp_obj_t arg) { - return mp_obj_get_int_base(arg, 0); -} - -machine_int_t mp_obj_get_int_base(mp_obj_t arg, mp_obj_t base_arg) { - const char *value; - int base; if (arg == mp_const_false) { return 0; } else if (arg == mp_const_true) { @@ -154,17 +160,6 @@ machine_int_t mp_obj_get_int_base(mp_obj_t arg, mp_obj_t base_arg) { // TODO work out if this should be floor, ceil or trunc return (machine_int_t)mp_obj_float_get(arg); #endif - } else if (MP_OBJ_IS_TYPE(arg, &str_type)) { - if (base_arg == 0) { - value = qstr_str(mp_obj_str_get(arg)); - return (machine_int_t)strtonum(value, 0); - } else if (MP_OBJ_IS_SMALL_INT(base_arg)) { - base = MP_OBJ_SMALL_INT_VALUE(base_arg); - value = qstr_str(mp_obj_str_get(arg)); - return (machine_int_t)strtonum(value, base); - } else { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "an integer is required")); - } } else { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); } @@ -34,6 +34,8 @@ typedef struct _mp_obj_base_t mp_obj_base_t; // - xxxx...xx10: a qstr, bits 2 and above are the value // - xxxx...xx00: a pointer to an mp_obj_base_t +// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range +#define MP_OBJ_FITS_SMALL_INT(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0) #define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0) #define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2) #define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0) @@ -57,7 +59,7 @@ typedef struct _mp_obj_base_t mp_obj_base_t; #define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, 3, 3, (mp_fun_3_t)fun_name) #define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, (~((machine_uint_t)0)), (mp_fun_var_t)fun_name) #define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, n_args_max, (mp_fun_var_t)fun_name) -#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, 0, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name) +#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, n_args_min, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name) // These macros are used to declare and define constant staticmethond and classmethod objects // You can put "static" in front of the definitions to make them local @@ -83,7 +85,11 @@ typedef mp_obj_t (*mp_fun_t)(void); typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *); typedef mp_obj_t (*mp_fun_kw_t)(mp_obj_t, struct _mp_map_t*); -typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o); +typedef enum { + PRINT_STR, PRINT_REPR +} mp_print_kind_t; + +typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind); typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, int n_args, const mp_obj_t *args); // args are in reverse order in the array typedef mp_obj_t (*mp_call_n_fun_t)(mp_obj_t fun, int n_args, const mp_obj_t *args); // args are in reverse order in the array typedef mp_obj_t (*mp_call_n_kw_fun_t)(mp_obj_t fun, int n_args, int n_kw, const mp_obj_t *args); // args are in reverse order in the array @@ -196,6 +202,8 @@ mp_obj_t mp_obj_new_none(void); mp_obj_t mp_obj_new_bool(bool value); mp_obj_t mp_obj_new_cell(mp_obj_t obj); mp_obj_t mp_obj_new_int(machine_int_t value); +mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value); +mp_obj_t mp_obj_new_int_from_long_str(const char *s); mp_obj_t mp_obj_new_str(qstr qstr); #if MICROPY_ENABLE_FLOAT mp_obj_t mp_obj_new_float(mp_float_t val); @@ -226,8 +234,8 @@ mp_obj_t mp_obj_new_module(qstr module_name); mp_obj_t mp_obj_get_type(mp_obj_t o_in); const char *mp_obj_get_type_str(mp_obj_t o_in); -void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in); -void mp_obj_print(mp_obj_t o); +void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind); +void mp_obj_print(mp_obj_t o, mp_print_kind_t kind); bool mp_obj_is_callable(mp_obj_t o_in); machine_int_t mp_obj_hash(mp_obj_t o_in); @@ -235,7 +243,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); bool mp_obj_less(mp_obj_t o1, mp_obj_t o2); machine_int_t mp_obj_get_int(mp_obj_t arg); -machine_int_t mp_obj_get_int_base(mp_obj_t arg, mp_obj_t base_arg); +machine_int_t mp_obj_parse_int(mp_obj_t arg, mp_obj_t base_arg); #if MICROPY_ENABLE_FLOAT mp_float_t mp_obj_get_float(mp_obj_t self_in); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); @@ -282,12 +290,23 @@ mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_im // tuple extern const mp_obj_type_t tuple_type; void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items); +void mp_obj_tuple_del(mp_obj_t self_in); // list extern const mp_obj_type_t list_type; mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items); void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); +mp_obj_t mp_obj_list_sort(mp_obj_t args, struct _mp_map_t *kwargs); + +// map (the python builtin, not the dict implementation detail) +extern const mp_obj_type_t map_type; + +// enumerate +extern const mp_obj_type_t enumerate_type; + +// filter +extern const mp_obj_type_t filter_type; // dict extern const mp_obj_type_t dict_type; @@ -303,6 +322,10 @@ void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item); extern const mp_obj_type_t slice_type; void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *stop, machine_int_t *step); +// zip +extern const mp_obj_type_t zip_type; + + // functions typedef struct _mp_obj_fun_native_t { // need this so we can define const objects (to go in ROM) mp_obj_base_t base; diff --git a/py/objbool.c b/py/objbool.c index da9a678063..66f9e902a6 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -13,7 +13,7 @@ typedef struct _mp_obj_bool_t { bool value; } mp_obj_bool_t; -static void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_bool_t *self = self_in; if (self->value) { print(env, "True"); diff --git a/py/objcomplex.c b/py/objcomplex.c index 1036bae420..bd103bbfab 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -21,7 +21,7 @@ typedef struct _mp_obj_complex_t { mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag); -void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { +void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_complex_t *o = o_in; if (o->real == 0) { print(env, "%.8gj", o->imag); diff --git a/py/objdict.c b/py/objdict.c index 6dbb1f316b..da1b5b9f5b 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -20,7 +20,7 @@ typedef struct _mp_obj_dict_t { static mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur); static mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in); -static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_dict_t *self = self_in; bool first = true; print(env, "{"); @@ -31,9 +31,9 @@ static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env print(env, ", "); } first = false; - mp_obj_print_helper(print, env, next->key); + mp_obj_print_helper(print, env, next->key, PRINT_REPR); print(env, ": "); - mp_obj_print_helper(print, env, next->value); + mp_obj_print_helper(print, env, next->value, PRINT_REPR); } print(env, "}"); } @@ -57,6 +57,12 @@ static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return elem->value; } } + case RT_COMPARE_OP_IN: + case RT_COMPARE_OP_NOT_IN: + { + mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP); + return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL)); + } default: // op not supported return NULL; @@ -344,7 +350,7 @@ static mp_obj_t dict_view_getiter(mp_obj_t view_in) { return o; } -static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type)); mp_obj_dict_view_t *self = self_in; bool first = true; @@ -357,15 +363,25 @@ static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void print(env, ", "); } first = false; - mp_obj_print_helper(print, env, next); + mp_obj_print_helper(print, env, next, PRINT_REPR); } print(env, "])"); } +static mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + /* only supported for the 'keys' kind until sets and dicts are refactored */ + mp_obj_dict_view_t *o = lhs_in; + if (o->kind != MP_DICT_VIEW_KEYS) return NULL; + if (op != RT_COMPARE_OP_IN && op != RT_COMPARE_OP_NOT_IN) return NULL; + return dict_binary_op(op, o->dict, rhs_in); +} + + static const mp_obj_type_t dict_view_type = { { &mp_const_type }, "dict_view", .print = dict_view_print, + .binary_op = dict_view_binary_op, .getiter = dict_view_getiter, }; diff --git a/py/objenumerate.c b/py/objenumerate.c new file mode 100644 index 0000000000..5bfd8a3370 --- /dev/null +++ b/py/objenumerate.c @@ -0,0 +1,53 @@ +#include <stdlib.h> +#include <assert.h> + +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" + +typedef struct _mp_obj_enumerate_t { + mp_obj_base_t base; + mp_obj_t iter; + machine_int_t cur; +} mp_obj_enumerate_t; + +static mp_obj_t enumerate_getiter(mp_obj_t self_in) { + return self_in; +} + +static mp_obj_t enumerate_iternext(mp_obj_t self_in); + +/* TODO: enumerate is one of the ones that can take args or kwargs. + Sticking to args for now */ +static mp_obj_t enumerate_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { + /* NOTE: args are backwards */ + assert(n_args > 0); + args += n_args - 1; + mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t); + o->base.type = &enumerate_type; + o->iter = rt_getiter(args[0]); + o->cur = n_args > 1 ? mp_obj_get_int(args[-1]) : 0; + + return o; +} + +const mp_obj_type_t enumerate_type = { + { &mp_const_type }, + "enumerate", + .make_new = enumerate_make_new, + .iternext = enumerate_iternext, + .getiter = enumerate_getiter, +}; + +static mp_obj_t enumerate_iternext(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &enumerate_type)); + mp_obj_enumerate_t *self = self_in; + mp_obj_t next = rt_iternext(self->iter); + if (next == mp_const_stop_iteration) { + return mp_const_stop_iteration; + } else { + mp_obj_t items[] = {MP_OBJ_NEW_SMALL_INT(self->cur++), next}; + return mp_obj_new_tuple(2, items); + } +} diff --git a/py/objexcept.c b/py/objexcept.c index 4708a27bfc..67e6d63155 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -8,105 +8,98 @@ #include "misc.h" #include "mpconfig.h" #include "obj.h" +#include "objtuple.h" +// This is unified class for C-level and Python-level exceptions +// Python-level exception have empty ->msg and all arguments are in +// args tuple. C-level excepttion likely have ->msg, and may as well +// have args tuple (or otherwise have it as NULL). typedef struct mp_obj_exception_t { mp_obj_base_t base; qstr id; - int n_args; - const void *args[]; + qstr msg; + mp_obj_tuple_t args; } mp_obj_exception_t; -void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { +void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_exception_t *o = o_in; - switch (o->n_args) { - case 0: + if (o->msg != 0) { + print(env, "%s: %s", qstr_str(o->id), qstr_str(o->msg)); + } else { + // Yes, that's how CPython has it + if (kind == PRINT_REPR) { print(env, "%s", qstr_str(o->id)); - break; - case 1: - print(env, "%s: %s", qstr_str(o->id), (const char*)o->args[0]); - break; - case 2: - print(env, "%s: ", qstr_str(o->id)); - print(env, (const char*)o->args[0], o->args[1]); - break; - default: // here we just assume at least 3 args, but only use first 3 - print(env, "%s: ", qstr_str(o->id)); - print(env, (const char*)o->args[0], o->args[1], o->args[2]); - break; + } + if (kind == PRINT_STR) { + if (o->args.len == 0) { + print(env, ""); + return; + } else if (o->args.len == 1) { + mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR); + return; + } + } + tuple_print(print, env, &o->args, kind); } } +// args in reversed order +static mp_obj_t exception_call(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + mp_obj_exception_t *base = self_in; + mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, n_args); + o->base.type = &exception_type; + o->id = base->id; + o->msg = 0; + o->args.len = n_args; + + // TODO: factor out as reusable copy_reversed() + int j = 0; + for (int i = n_args - 1; i >= 0; i--) { + o->args.items[i] = args[j++]; + } + return o; +} + const mp_obj_type_t exception_type = { { &mp_const_type }, "exception", .print = exception_print, + .call_n = exception_call, }; mp_obj_t mp_obj_new_exception(qstr id) { - mp_obj_exception_t *o = m_new_obj(mp_obj_exception_t); - o->base.type = &exception_type; - o->id = id; - o->n_args = 0; - return o; + return mp_obj_new_exception_msg_varg(id, NULL); } mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) { - mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 1); - o->base.type = &exception_type; - o->id = id; - o->n_args = 1; - o->args[0] = msg; - return o; + return mp_obj_new_exception_msg_varg(id, msg); } mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1) { - mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 2); - o->base.type = &exception_type; - o->id = id; - o->n_args = 2; - o->args[0] = fmt; - o->args[1] = a1; - return o; + return mp_obj_new_exception_msg_varg(id, fmt, a1); } mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2) { - mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 3); - o->base.type = &exception_type; - o->id = id; - o->n_args = 3; - o->args[0] = fmt; - o->args[1] = a1; - o->args[2] = a2; - return o; + return mp_obj_new_exception_msg_varg(id, fmt, a1, a2); } mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) { - // count number of arguments by number of % signs, excluding %% - int n_args = 1; // count fmt - for (const char *s = fmt; *s; s++) { - if (*s == '%') { - if (s[1] == '%') { - s += 1; - } else { - n_args += 1; - } - } - } - // make exception object - mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, n_args); + mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0); o->base.type = &exception_type; o->id = id; - o->n_args = n_args; - o->args[0] = fmt; - - // extract args and store them - va_list ap; - va_start(ap, fmt); - for (int i = 1; i < n_args; i++) { - o->args[i] = va_arg(ap, void*); + o->args.len = 0; + if (fmt == NULL) { + o->msg = 0; + } else { + // render exception message + vstr_t *vstr = vstr_new(); + va_list ap; + va_start(ap, fmt); + vstr_vprintf(vstr, fmt, ap); + va_end(ap); + o->msg = qstr_from_str_take(vstr->buf, vstr->alloc); } - va_end(ap); return o; } diff --git a/py/objfilter.c b/py/objfilter.c new file mode 100644 index 0000000000..18225ac102 --- /dev/null +++ b/py/objfilter.c @@ -0,0 +1,58 @@ +#include <stdlib.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "mpqstr.h" +#include "obj.h" +#include "runtime.h" + +typedef struct _mp_obj_filter_t { + mp_obj_base_t base; + mp_obj_t fun; + mp_obj_t iter; +} mp_obj_filter_t; + +static mp_obj_t filter_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { + /* NOTE: args are backwards */ + if (n_args != 2) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "filter expected 2 arguments")); + } + assert(n_args == 2); + mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t); + o->base.type = &filter_type; + o->fun = args[1]; + o->iter = rt_getiter(args[0]); + return o; +} + +static mp_obj_t filter_getiter(mp_obj_t self_in) { + return self_in; +} + +static mp_obj_t filter_iternext(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &filter_type)); + mp_obj_filter_t *self = self_in; + mp_obj_t next; + while ((next = rt_iternext(self->iter)) != mp_const_stop_iteration) { + mp_obj_t val; + if (self->fun != mp_const_none) { + val = rt_call_function_n(self->fun, 1, &next); + } else { + val = next; + } + if (rt_is_true(val)) { + return next; + } + } + return mp_const_stop_iteration; +} + +const mp_obj_type_t filter_type = { + { &mp_const_type }, + "filter", + .make_new = filter_make_new, + .getiter = filter_getiter, + .iternext = filter_iternext, +}; diff --git a/py/objfloat.c b/py/objfloat.c index bb44ac9549..1ac8754e40 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -19,7 +19,7 @@ typedef struct _mp_obj_float_t { mp_obj_t mp_obj_new_float(mp_float_t value); -static void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { +static void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_float_t *o = o_in; print(env, "%.8g", o->value); } diff --git a/py/objfun.c b/py/objfun.c index afac3889fd..c624cf2d27 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -17,21 +17,44 @@ // mp_obj_fun_native_t defined in obj.h +void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) { + if (n_kw && !self->is_kw) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, + "function does not take keyword arguments")); + } + + if (self->n_args_min == self->n_args_max) { + if (n_args != self->n_args_min) { + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, + "function takes %d positional arguments but %d were given", + (const char*)(machine_int_t)self->n_args_min, + (const char*)(machine_int_t)n_args)); + } + } else { + if (n_args < self->n_args_min) { + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, + "<fun name>() missing %d required positional arguments: <list of names of params>", + (const char*)(machine_int_t)(self->n_args_min - n_args))); + } else if (n_args > self->n_args_max) { + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, + "<fun name> expected at most %d arguments, got %d", + (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args)); + } + } +} + mp_obj_t fun_native_call_n_kw(mp_obj_t self_in, int n_args, int n_kw, const mp_obj_t *args); // args are in reverse order in the array mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { mp_obj_fun_native_t *self = self_in; + // check number of arguments + check_nargs(self, n_args, 0); if (self->is_kw) { return fun_native_call_n_kw(self_in, n_args, 0, args); } if (self->n_args_min == self->n_args_max) { // function requires a fixed number of arguments - // check number of arguments - if (n_args != self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args)); - } - // dispatch function call switch (self->n_args_min) { case 0: @@ -54,12 +77,6 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { } else { // function takes a variable number of arguments - if (n_args < self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(self->n_args_min - n_args))); - } else if (n_args > self->n_args_max) { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "<fun name> expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args)); - } - // TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args mp_obj_t *args_ordered = m_new(mp_obj_t, n_args); for (int i = 0; i < n_args; i++) { @@ -76,9 +93,7 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { mp_obj_t fun_native_call_n_kw(mp_obj_t self_in, int n_args, int n_kw, const mp_obj_t *args) { mp_obj_fun_native_t *self = self_in; - if (!self->is_kw) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments")); - } + check_nargs(self, n_args, n_kw); mp_obj_t *vargs = mp_obj_new_tuple_reverse(n_args, args + 2*n_kw); mp_map_t *kw_args = mp_map_new(n_kw); @@ -98,38 +113,13 @@ const mp_obj_type_t fun_native_type = { .call_n_kw = fun_native_call_n_kw, }; -mp_obj_t rt_make_function_0(mp_fun_0_t fun) { - mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); - o->base.type = &fun_native_type; - o->n_args_min = 0; - o->n_args_max = 0; - o->fun = fun; - return o; -} - -mp_obj_t rt_make_function_1(mp_fun_1_t fun) { - mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); - o->base.type = &fun_native_type; - o->n_args_min = 1; - o->n_args_max = 1; - o->fun = fun; - return o; -} - -mp_obj_t rt_make_function_2(mp_fun_2_t fun) { - mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); - o->base.type = &fun_native_type; - o->n_args_min = 2; - o->n_args_max = 2; - o->fun = fun; - return o; -} - -mp_obj_t rt_make_function_3(mp_fun_3_t fun) { +// fun must have the correct signature for n_args fixed arguments +mp_obj_t rt_make_function_n(int n_args, void *fun) { mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); o->base.type = &fun_native_type; - o->n_args_min = 3; - o->n_args_max = 3; + o->is_kw = false; + o->n_args_min = n_args; + o->n_args_max = n_args; o->fun = fun; return o; } @@ -137,6 +127,7 @@ mp_obj_t rt_make_function_3(mp_fun_3_t fun) { mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t fun) { mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); o->base.type = &fun_native_type; + o->is_kw = false; o->n_args_min = n_args_min; o->n_args_max = ~((machine_uint_t)0); o->fun = fun; @@ -147,6 +138,7 @@ mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t fun) { mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun) { mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); o->base.type = &fun_native_type; + o->is_kw = false; o->n_args_min = n_args_min; o->n_args_max = n_args_max; o->fun = fun; diff --git a/py/objgenerator.c b/py/objgenerator.c index 7eeb4ef80b..40f202df3c 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -61,7 +61,7 @@ typedef struct _mp_obj_gen_instance_t { mp_obj_t state[]; } mp_obj_gen_instance_t; -void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { print(env, "<generator object 'fun-name' at %p>", self_in); } diff --git a/py/objint.c b/py/objint.c index bd0926840b..937bff7ae3 100644 --- a/py/objint.c +++ b/py/objint.c @@ -8,21 +8,27 @@ #include "mpconfig.h" #include "mpqstr.h" #include "obj.h" +#include "objint.h" -typedef struct _mp_obj_int_t { - mp_obj_base_t base; -} mp_obj_int_t; - +// This dispatcher function is expected to be independent of the implementation +// of long int static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { switch (n_args) { case 0: return MP_OBJ_NEW_SMALL_INT(0); case 1: - return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0])); + if (MP_OBJ_IS_TYPE(args[0], &str_type)) { + // a string, parse it + return MP_OBJ_NEW_SMALL_INT(strtonum(qstr_str(mp_obj_get_qstr(args[0])), 0)); + } else { + return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0])); + } case 2: - return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int_base(args[1], args[0])); + // should be a string, parse it + // TODO proper error checking of argument types + return MP_OBJ_NEW_SMALL_INT(strtonum(qstr_str(mp_obj_get_qstr(args[1])), mp_obj_get_int(args[0]))); default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "int takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args)); @@ -32,9 +38,45 @@ static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) const mp_obj_type_t int_type = { { &mp_const_type }, "int", + .print = int_print, .make_new = int_make_new, + .binary_op = int_binary_op, }; +#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE +// This is called only for non-SMALL_INT +void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { +} + +// This is called only for non-SMALL_INT +mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + assert(0); + return mp_const_none; +} + +// This is called only with strings whose value doesn't fit in SMALL_INT +mp_obj_t mp_obj_new_int_from_long_str(const char *s) { + assert(0); + return mp_const_none; +} + +mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) { + // SMALL_INT accepts only signed numbers, of one bit less size + // then word size, which totals 2 bits less for unsigned numbers. + if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) { + return MP_OBJ_NEW_SMALL_INT(value); + } + // TODO: Raise exception + assert(0); + return mp_const_none; +} + mp_obj_t mp_obj_new_int(machine_int_t value) { - return MP_OBJ_NEW_SMALL_INT(value); + if (MP_OBJ_FITS_SMALL_INT(value)) { + return MP_OBJ_NEW_SMALL_INT(value); + } + // TODO: Raise exception + assert(0); + return mp_const_none; } +#endif diff --git a/py/objint.h b/py/objint.h new file mode 100644 index 0000000000..7d43971ec3 --- /dev/null +++ b/py/objint.h @@ -0,0 +1,9 @@ +typedef struct _mp_obj_int_t { + mp_obj_base_t base; +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE + mp_longint_impl_t val; +#endif +} mp_obj_int_t; + +void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind); +mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in); diff --git a/py/objlist.c b/py/objlist.c index c153d2222b..829677b43b 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -26,14 +26,14 @@ static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in); /******************************************************************************/ /* list */ -static void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { +static void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_list_t *o = o_in; print(env, "["); for (int i = 0; i < o->len; i++) { if (i > 0) { print(env, ", "); } - mp_obj_print_helper(print, env, o->items[i]); + mp_obj_print_helper(print, env, o->items[i], PRINT_REPR); } print(env, "]"); } @@ -62,6 +62,61 @@ static mp_obj_t list_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args return NULL; } +// Don't pass RT_COMPARE_OP_NOT_EQUAL here +static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) { + assert(MP_OBJ_IS_TYPE(self_in, &list_type)); + if (!MP_OBJ_IS_TYPE(another_in, &list_type)) { + return false; + } + mp_obj_list_t *self = self_in; + mp_obj_list_t *another = another_in; + if (op == RT_COMPARE_OP_EQUAL && self->len != another->len) { + return false; + } + + // Let's deal only with > & >= + if (op == RT_COMPARE_OP_LESS || op == RT_COMPARE_OP_LESS_EQUAL) { + mp_obj_t t = self; + self = another; + another = t; + if (op == RT_COMPARE_OP_LESS) { + op = RT_COMPARE_OP_MORE; + } else { + op = RT_COMPARE_OP_MORE_EQUAL; + } + } + + int len = self->len < another->len ? self->len : another->len; + bool eq_status = true; // empty lists are equal + bool rel_status; + for (int i = 0; i < len; i++) { + eq_status = mp_obj_equal(self->items[i], another->items[i]); + if (op == RT_COMPARE_OP_EQUAL && !eq_status) { + return false; + } + rel_status = (rt_binary_op(op, self->items[i], another->items[i]) == mp_const_true); + if (!eq_status && !rel_status) { + return false; + } + } + + // If we had tie in the last element... + if (eq_status) { + // ... and we have lists of different lengths... + if (self->len != another->len) { + if (self->len < another->len) { + // ... then longer list length wins (we deal only with >) + return false; + } + } else if (op == RT_COMPARE_OP_MORE) { + // Otherwise, if we have strict relation, equality means failure + return false; + } + } + + return true; +} + static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_list_t *o = lhs; switch (op) { @@ -105,6 +160,15 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } return s; } + case RT_COMPARE_OP_EQUAL: + case RT_COMPARE_OP_LESS: + case RT_COMPARE_OP_LESS_EQUAL: + case RT_COMPARE_OP_MORE: + case RT_COMPARE_OP_MORE_EQUAL: + return MP_BOOL(list_cmp_helper(op, lhs, rhs)); + case RT_COMPARE_OP_NOT_EQUAL: + return MP_BOOL(!list_cmp_helper(RT_COMPARE_OP_EQUAL, lhs, rhs)); + default: // op not supported return NULL; @@ -184,13 +248,14 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool r } } -static mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs) { +mp_obj_t mp_obj_list_sort(mp_obj_t args, mp_map_t *kwargs) { mp_obj_t *args_items = NULL; uint args_len = 0; assert(MP_OBJ_IS_TYPE(args, &tuple_type)); mp_obj_tuple_get(args, &args_len, &args_items); assert(args_len >= 1); + assert(MP_OBJ_IS_TYPE(args_items[0], &list_type)); if (args_len > 1) { nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "list.sort takes no positional arguments")); @@ -316,7 +381,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop); static MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, list_remove); static MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse); -static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, list_sort); +static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 0, mp_obj_list_sort); static const mp_method_t list_type_methods[] = { { "append", &list_append_obj }, diff --git a/py/objmap.c b/py/objmap.c new file mode 100644 index 0000000000..365735283a --- /dev/null +++ b/py/objmap.c @@ -0,0 +1,60 @@ +#include <stdlib.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "mpqstr.h" +#include "obj.h" +#include "runtime.h" + +typedef struct _mp_obj_map_t { + mp_obj_base_t base; + machine_uint_t n_iters; + mp_obj_t fun; + mp_obj_t iters[]; +} mp_obj_map_t; + +static mp_obj_t map_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { + /* NOTE: args are backwards */ + if (n_args < 2) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "map must have at least 2 arguments")); + } + assert(n_args >= 2); + mp_obj_map_t *o = m_new_obj_var(mp_obj_map_t, mp_obj_t, n_args - 1); + o->base.type = &map_type; + o->n_iters = n_args - 1; + o->fun = args[n_args - 1]; + for (int i = 0; i < n_args - 1; i++) { + o->iters[i] = rt_getiter(args[n_args-i-2]); + } + return o; +} + +static mp_obj_t map_getiter(mp_obj_t self_in) { + return self_in; +} + +static mp_obj_t map_iternext(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &map_type)); + mp_obj_map_t *self = self_in; + mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters); + + for (int i = 0; i < self->n_iters; i++) { + mp_obj_t next = rt_iternext(self->iters[i]); + if (next == mp_const_stop_iteration) { + m_del(mp_obj_t, nextses, self->n_iters); + return mp_const_stop_iteration; + } + nextses[i] = next; + } + return rt_call_function_n(self->fun, self->n_iters, nextses); +} + +const mp_obj_type_t map_type = { + { &mp_const_type }, + "map", + .make_new = map_make_new, + .getiter = map_getiter, + .iternext = map_iternext, +}; diff --git a/py/objmodule.c b/py/objmodule.c index ade9369176..50d2bb35ed 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -17,7 +17,7 @@ typedef struct _mp_obj_module_t { mp_map_t *globals; } mp_obj_module_t; -static void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_module_t *self = self_in; print(env, "<module '%s' from '-unknown-file-'>", qstr_str(self->name)); } diff --git a/py/objnone.c b/py/objnone.c index c0efe6c0f5..84d0ba164c 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -10,7 +10,7 @@ typedef struct _mp_obj_none_t { mp_obj_base_t base; } mp_obj_none_t; -void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { print(env, "None"); } diff --git a/py/objset.c b/py/objset.c index 67dab11dfb..6ea6d62d8f 100644 --- a/py/objset.c +++ b/py/objset.c @@ -1,5 +1,6 @@ #include <stdlib.h> #include <stdint.h> +#include <string.h> #include <assert.h> #include "nlr.h" @@ -8,6 +9,7 @@ #include "mpqstr.h" #include "obj.h" #include "runtime.h" +#include "runtime0.h" #include "map.h" typedef struct _mp_obj_set_t { @@ -15,8 +17,20 @@ typedef struct _mp_obj_set_t { mp_set_t set; } mp_obj_set_t; -void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +typedef struct _mp_obj_set_it_t { + mp_obj_base_t base; + mp_obj_set_t *set; + machine_uint_t cur; +} mp_obj_set_it_t; + +static mp_obj_t set_it_iternext(mp_obj_t self_in); + +void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_set_t *self = self_in; + if (self->set.used == 0) { + print(env, "set()"); + return; + } bool first = true; print(env, "{"); for (int i = 0; i < self->set.alloc; i++) { @@ -25,12 +39,13 @@ void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj print(env, ", "); } first = false; - mp_obj_print_helper(print, env, self->set.table[i]); + mp_obj_print_helper(print, env, self->set.table[i], PRINT_REPR); } } print(env, "}"); } + static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { switch (n_args) { case 0: @@ -54,11 +69,389 @@ static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) } } +const mp_obj_type_t set_it_type = { + { &mp_const_type }, + "set_iterator", + .iternext = set_it_iternext, +}; + +static mp_obj_t set_it_iternext(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_it_type)); + mp_obj_set_it_t *self = self_in; + machine_uint_t max = self->set->set.alloc; + mp_obj_t *table = self->set->set.table; + + for (machine_uint_t i = self->cur; i < max; i++) { + if (table[i] != NULL) { + self->cur = i + 1; + return table[i]; + } + } + + return mp_const_stop_iteration; +} + +static mp_obj_t set_getiter(mp_obj_t set_in) { + mp_obj_set_it_t *o = m_new_obj(mp_obj_set_it_t); + o->base.type = &set_it_type; + o->set = (mp_obj_set_t *)set_in; + o->cur = 0; + return o; +} + + +/******************************************************************************/ +/* set methods */ + +static mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add); + +static mp_obj_t set_clear(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + + mp_set_clear(&self->set); + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear); + +static mp_obj_t set_copy(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + + mp_obj_set_t *other = m_new_obj(mp_obj_set_t); + other->base.type = &set_type; + mp_set_init(&other->set, self->set.alloc - 1); + other->set.used = self->set.used; + memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t)); + + return other; +} +static MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy); + +static mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard); + +static mp_obj_t set_diff_int(int n_args, const mp_obj_t *args, bool update) { + assert(n_args > 0); + assert(MP_OBJ_IS_TYPE(args[0], &set_type)); + mp_obj_set_t *self; + if (update) { + self = args[0]; + } else { + self = set_copy(args[0]); + } + + + for (int i = 1; i < n_args; i++) { + mp_obj_t other = args[i]; + if (self == other) { + set_clear(self); + } else { + mp_obj_t iter = rt_getiter(other); + mp_obj_t next; + while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { + set_discard(self, next); + } + } + } + + return self; +} + +static mp_obj_t set_diff(int n_args, const mp_obj_t *args) { + return set_diff_int(n_args, args, false); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff); + +static mp_obj_t set_diff_update(int n_args, const mp_obj_t *args) { + set_diff_int(n_args, args, true); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update); + +static mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + if (self_in == other) { + return update ? mp_const_none : set_copy(self_in); + } + + mp_obj_set_t *self = self_in; + mp_obj_set_t *out = mp_obj_new_set(0, NULL); + + mp_obj_t iter = rt_getiter(other); + mp_obj_t next; + while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { + if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { + set_add(out, next); + } + } + + if (update) { + m_del(mp_obj_t, self->set.table, self->set.alloc); + self->set.alloc = out->set.alloc; + self->set.used = out->set.used; + self->set.table = out->set.table; + } + + return update ? mp_const_none : out; +} + +static mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) { + return set_intersect_int(self_in, other, false); +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect); + +static mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) { + return set_intersect_int(self_in, other, true); +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update); + +static mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + + mp_obj_t iter = rt_getiter(other); + mp_obj_t next; + while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { + if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) { + return mp_const_false; + } + } + return mp_const_true; +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint); + +static mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) { + mp_obj_set_t *self; + bool cleanup_self = false; + if (MP_OBJ_IS_TYPE(self_in, &set_type)) { + self = self_in; + } else { + self = set_make_new(NULL, 1, &self_in); + cleanup_self = true; + } + + mp_obj_set_t *other; + bool cleanup_other = false; + if (MP_OBJ_IS_TYPE(other_in, &set_type)) { + other = other_in; + } else { + other = set_make_new(NULL, 1, &other_in); + cleanup_other = true; + } + bool out = true; + if (proper && self->set.used == other->set.used) { + out = false; + } else { + mp_obj_t iter = set_getiter(self); + mp_obj_t next; + while ((next = set_it_iternext(iter)) != mp_const_stop_iteration) { + if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) { + out = false; + break; + } + } + } + if (cleanup_self) { + set_clear(self); + } + if (cleanup_other) { + set_clear(other); + } + return MP_BOOL(out); +} +static mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) { + return set_issubset_internal(self_in, other_in, false); +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset); + +static mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) { + return set_issubset_internal(self_in, other_in, true); +} + +static mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) { + return set_issubset_internal(other_in, self_in, false); +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset); + +static mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) { + return set_issubset_internal(other_in, self_in, true); +} + +static mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + if (!MP_OBJ_IS_TYPE(other_in, &set_type)) { + return mp_const_false; + } + mp_obj_set_t *other = other_in; + if (self->set.used != other->set.used) { + return mp_const_false; + } + return set_issubset(self_in, other_in); +} + +static mp_obj_t set_pop(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + + if (self->set.used == 0) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "pop from an empty set")); + } + mp_obj_t obj = mp_set_lookup(&self->set, NULL, + MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_FIRST); + return obj; +} +static MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop); + +static mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) { + nlr_jump(mp_obj_new_exception(MP_QSTR_KeyError)); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove); + +static mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + mp_obj_t iter = rt_getiter(other_in); + mp_obj_t next; + while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { + mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update); + +static mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + self_in = set_copy(self_in); + set_symmetric_difference_update(self_in, other_in); + return self_in; +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference); + +static void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) { + mp_obj_t iter = rt_getiter(other_in); + mp_obj_t next; + while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { + mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + } +} + +static mp_obj_t set_update(int n_args, const mp_obj_t *args) { + assert(n_args > 0); + assert(MP_OBJ_IS_TYPE(args[0], &set_type)); + + for (int i = 1; i < n_args; i++) { + set_update_int(args[0], args[i]); + } + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update); + +static mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = set_copy(self_in); + set_update_int(self, other_in); + return self; +} +static MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union); + + +static mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { + mp_obj_t args[] = {lhs, rhs}; + switch (op) { + case RT_BINARY_OP_OR: + return set_union(lhs, rhs); + case RT_BINARY_OP_XOR: + return set_symmetric_difference(lhs, rhs); + case RT_BINARY_OP_AND: + return set_intersect(lhs, rhs); + case RT_BINARY_OP_SUBTRACT: + return set_diff(2, args); + case RT_BINARY_OP_INPLACE_OR: + return set_union(lhs, rhs); + case RT_BINARY_OP_INPLACE_XOR: + return set_symmetric_difference(lhs, rhs); + case RT_BINARY_OP_INPLACE_AND: + return set_intersect(lhs, rhs); + case RT_BINARY_OP_INPLACE_SUBTRACT: + return set_diff(2, args); + case RT_COMPARE_OP_LESS: + return set_issubset_proper(lhs, rhs); + case RT_COMPARE_OP_MORE: + return set_issuperset_proper(lhs, rhs); + case RT_COMPARE_OP_EQUAL: + return set_equal(lhs, rhs); + case RT_COMPARE_OP_LESS_EQUAL: + return set_issubset(lhs, rhs); + case RT_COMPARE_OP_MORE_EQUAL: + return set_issuperset(lhs, rhs); + case RT_COMPARE_OP_NOT_EQUAL: + return MP_BOOL(set_equal(lhs, rhs) == mp_const_false); + case RT_COMPARE_OP_IN: + case RT_COMPARE_OP_NOT_IN: + { + mp_obj_set_t *o = lhs; + mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP); + return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL)); + } + default: + // op not supported + return NULL; + } +} + +/******************************************************************************/ +/* set constructors & public C API */ + + +static const mp_method_t set_type_methods[] = { + { "add", &set_add_obj }, + { "clear", &set_clear_obj }, + { "copy", &set_copy_obj }, + { "discard", &set_discard_obj }, + { "difference", &set_diff_obj }, + { "difference_update", &set_diff_update_obj }, + { "intersection", &set_intersect_obj }, + { "intersection_update", &set_intersect_update_obj }, + { "isdisjoint", &set_isdisjoint_obj }, + { "issubset", &set_issubset_obj }, + { "issuperset", &set_issuperset_obj }, + { "pop", &set_pop_obj }, + { "remove", &set_remove_obj }, + { "symmetric_difference", &set_symmetric_difference_obj }, + { "symmetric_difference_update", &set_symmetric_difference_update_obj }, + { "union", &set_union_obj }, + { "update", &set_update_obj }, + { NULL, NULL }, // end-of-list sentinel +}; + const mp_obj_type_t set_type = { { &mp_const_type }, "set", .print = set_print, .make_new = set_make_new, + .binary_op = set_binary_op, + .getiter = set_getiter, + .methods = set_type_methods, }; mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) { @@ -66,7 +459,7 @@ mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) { o->base.type = &set_type; mp_set_init(&o->set, n_args); for (int i = 0; i < n_args; i++) { - mp_set_lookup(&o->set, items[i], true); + mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } return o; } @@ -74,5 +467,5 @@ mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) { void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) { assert(MP_OBJ_IS_TYPE(self_in, &set_type)); mp_obj_set_t *self = self_in; - mp_set_lookup(&self->set, item, true); + mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } diff --git a/py/objslice.c b/py/objslice.c index d95ccef06f..8abcea08d0 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -16,7 +16,7 @@ typedef struct _mp_obj_ellipsis_t { mp_obj_base_t base; } mp_obj_ellipsis_t; -void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { print(env, "Ellipsis"); } @@ -42,7 +42,7 @@ typedef struct _mp_obj_slice_t { machine_int_t stop; } mp_obj_slice_t; -void slice_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { +void slice_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_slice_t *o = o_in; print(env, "slice(" INT_FMT ", " INT_FMT ")", o->start, o->stop); } diff --git a/py/objstr.c b/py/objstr.c index ea4f5ead24..0621a8df75 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -22,10 +22,14 @@ static mp_obj_t mp_obj_new_str_iterator(mp_obj_str_t *str, int cur); /******************************************************************************/ /* str */ -void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_str_t *self = self_in; - // TODO need to escape chars etc - print(env, "'%s'", qstr_str(self->qstr)); + if (kind == PRINT_STR) { + print(env, "%s", qstr_str(self->qstr)); + } else { + // TODO need to escape chars etc + print(env, "'%s'", qstr_str(self->qstr)); + } } mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { @@ -85,6 +89,15 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return mp_obj_new_str(qstr_from_str_take(val, alloc_len)); } break; + case RT_COMPARE_OP_IN: + case RT_COMPARE_OP_NOT_IN: + /* NOTE `a in b` is `b.__contains__(a)` */ + if (MP_OBJ_IS_TYPE(rhs_in, &str_type)) { + const char *rhs_str = qstr_str(((mp_obj_str_t*)rhs_in)->qstr); + /* FIXME \0 in strs */ + return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (strstr(lhs_str, rhs_str) == NULL)); + } + break; } return MP_OBJ_NULL; // op not supported @@ -156,6 +169,46 @@ static bool chr_in_str(const char* const str, const size_t str_len, const char c return false; } +static mp_obj_t str_find(int n_args, const mp_obj_t *args) { + assert(2 <= n_args && n_args <= 4); + assert(MP_OBJ_IS_TYPE(args[0], &str_type)); + if (!MP_OBJ_IS_TYPE(args[1], &str_type)) { + nlr_jump(mp_obj_new_exception_msg_1_arg( + MP_QSTR_TypeError, + "Can't convert '%s' object to str implicitly", + mp_obj_get_type_str(args[1]))); + } + + const char* haystack = qstr_str(((mp_obj_str_t*)args[0])->qstr); + const char* needle = qstr_str(((mp_obj_str_t*)args[1])->qstr); + + size_t haystack_len = strlen(haystack); + size_t needle_len = strlen(needle); + + size_t start = 0; + size_t end = haystack_len; + /* TODO use a non-exception-throwing mp_get_index */ + if (n_args >= 3 && args[2] != mp_const_none) { + start = mp_get_index(&str_type, haystack_len, args[2]); + } + if (n_args >= 4 && args[3] != mp_const_none) { + end = mp_get_index(&str_type, haystack_len, args[3]); + } + + char *p = strstr(haystack + start, needle); + if (p == NULL) { + // not found + return MP_OBJ_NEW_SMALL_INT(-1); + } else { + // found + machine_int_t pos = p - haystack; + if (pos + needle_len > end) { + pos = -1; + } + return MP_OBJ_NEW_SMALL_INT(pos); + } +} + mp_obj_t str_strip(int n_args, const mp_obj_t *args) { assert(1 <= n_args && n_args <= 2); assert(MP_OBJ_IS_TYPE(args[0], &str_type)); @@ -205,13 +258,6 @@ mp_obj_t str_strip(int n_args, const mp_obj_t *args) { return mp_obj_new_str(qstr_from_str_take(stripped_str, stripped_len + 1)); } -void vstr_printf_wrapper(void *env, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vstr_vprintf(env, fmt, args); - va_end(args); -} - mp_obj_t str_format(int n_args, const mp_obj_t *args) { assert(MP_OBJ_IS_TYPE(args[0], &str_type)); mp_obj_str_t *self = args[0]; @@ -228,7 +274,8 @@ mp_obj_t str_format(int n_args, const mp_obj_t *args) { if (arg_i >= n_args) { nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range")); } - mp_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]); + // TODO: may be PRINT_REPR depending on formatting code + mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_STR); arg_i++; } } else { @@ -239,11 +286,13 @@ mp_obj_t str_format(int n_args, const mp_obj_t *args) { return mp_obj_new_str(qstr_from_str_take(vstr->buf, vstr->alloc)); } +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find); static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format); static const mp_method_t str_type_methods[] = { + { "find", &str_find_obj }, { "join", &str_join_obj }, { "strip", &str_strip_obj }, { "format", &str_format_obj }, diff --git a/py/objtuple.c b/py/objtuple.c index 7685cc449f..a64b1fa16c 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -9,26 +9,21 @@ #include "obj.h" #include "runtime0.h" #include "runtime.h" - -typedef struct _mp_obj_tuple_t { - mp_obj_base_t base; - machine_uint_t len; - mp_obj_t items[]; -} mp_obj_tuple_t; +#include "objtuple.h" static mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, int cur); /******************************************************************************/ /* tuple */ -static void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { +void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_tuple_t *o = o_in; print(env, "("); for (int i = 0; i < o->len; i++) { if (i > 0) { print(env, ", "); } - mp_obj_print_helper(print, env, o->items[i]); + mp_obj_print_helper(print, env, o->items[i], PRINT_REPR); } if (o->len == 1) { print(env, ","); @@ -116,8 +111,10 @@ mp_obj_t mp_obj_new_tuple(uint n, const mp_obj_t *items) { mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n); o->base.type = &tuple_type; o->len = n; - for (int i = 0; i < n; i++) { - o->items[i] = items[i]; + if (items) { + for (int i = 0; i < n; i++) { + o->items[i] = items[i]; + } } return o; } @@ -138,8 +135,18 @@ mp_obj_t mp_obj_new_tuple_reverse(uint n, const mp_obj_t *items) { void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) { assert(MP_OBJ_IS_TYPE(self_in, &tuple_type)); mp_obj_tuple_t *self = self_in; - *len = self->len; - *items = &self->items[0]; + if (len) { + *len = self->len; + } + if (items) { + *items = &self->items[0]; + } +} + +void mp_obj_tuple_del(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &tuple_type)); + mp_obj_tuple_t *self = self_in; + m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self); } /******************************************************************************/ diff --git a/py/objtuple.h b/py/objtuple.h new file mode 100644 index 0000000000..6ff38c10eb --- /dev/null +++ b/py/objtuple.h @@ -0,0 +1,7 @@ +typedef struct _mp_obj_tuple_t { + mp_obj_base_t base; + machine_uint_t len; + mp_obj_t items[]; +} mp_obj_tuple_t; + +void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind); diff --git a/py/objtype.c b/py/objtype.c index 011ee43552..5a2f96d6b0 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -66,7 +66,7 @@ static mp_map_elem_t *mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr, } } -static void class_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void class_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { print(env, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in); } @@ -148,7 +148,7 @@ static bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { // - there is a constant mp_obj_type_t (called mp_const_type) for the 'type' object // - creating a new class (a new type) creates a new mp_obj_type_t -static void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_type_t *self = self_in; print(env, "<class '%s'>", self->name); } diff --git a/py/objzip.c b/py/objzip.c new file mode 100644 index 0000000000..a552ff5881 --- /dev/null +++ b/py/objzip.c @@ -0,0 +1,57 @@ +#include <stdlib.h> +#include <assert.h> + +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" + +typedef struct _mp_obj_zip_t { + mp_obj_base_t base; + int n_iters; + mp_obj_t iters[]; +} mp_obj_zip_t; + +static mp_obj_t zip_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { + /* NOTE: args are backwards */ + mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args); + o->base.type = &zip_type; + o->n_iters = n_args; + for (int i = 0; i < n_args; i++) { + o->iters[i] = rt_getiter(args[n_args-i-1]); + } + return o; +} + +static mp_obj_t zip_getiter(mp_obj_t self_in) { + return self_in; +} + +static mp_obj_t zip_iternext(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &zip_type)); + mp_obj_zip_t *self = self_in; + mp_obj_t *items; + if (self->n_iters == 0) { + return mp_const_stop_iteration; + } + mp_obj_t o = mp_obj_new_tuple(self->n_iters, NULL); + mp_obj_tuple_get(o, NULL, &items); + + for (int i = 0; i < self->n_iters; i++) { + mp_obj_t next = rt_iternext(self->iters[i]); + if (next == mp_const_stop_iteration) { + mp_obj_tuple_del(o); + return mp_const_stop_iteration; + } + items[i] = next; + } + return o; +} + +const mp_obj_type_t zip_type = { + { &mp_const_type }, + "zip", + .make_new = zip_make_new, + .getiter = zip_getiter, + .iternext = zip_iternext, +}; diff --git a/py/parse.c b/py/parse.c index d3786ba956..49b42e5d77 100644 --- a/py/parse.c +++ b/py/parse.c @@ -8,6 +8,7 @@ #include "misc.h" #include "mpconfig.h" +#include "mpqstr.h" #include "lexer.h" #include "parse.h" @@ -88,6 +89,7 @@ typedef struct _parser_t { uint rule_stack_top; rule_stack_t *rule_stack; + uint result_stack_alloc; uint result_stack_top; mp_parse_node_t *result_stack; } parser_t; @@ -121,7 +123,7 @@ mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) { int num_parse_nodes_allocated = 0; mp_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) { - mp_parse_node_struct_t *pn = m_malloc(sizeof(mp_parse_node_struct_t) + num_args * sizeof(mp_parse_node_t)); + mp_parse_node_struct_t *pn = m_new_obj_var(mp_parse_node_struct_t, mp_parse_node_t, num_args); pn->source = 0; // TODO pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8); num_parse_nodes_allocated += 1; @@ -180,6 +182,10 @@ static mp_parse_node_t peek_result(parser_t *parser, int pos) { } static void push_result_node(parser_t *parser, mp_parse_node_t pn) { + if (parser->result_stack_top >= parser->result_stack_alloc) { + parser->result_stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc * 2); + parser->result_stack_alloc *= 2; + } parser->result_stack[parser->result_stack_top++] = pn; } @@ -191,7 +197,7 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) { } else if (tok->kind == MP_TOKEN_NUMBER) { bool dec = false; bool small_int = true; - int int_val = 0; + machine_int_t int_val = 0; int len = tok->len; const char *str = tok->str; int base = 10; @@ -211,7 +217,9 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) { i = 2; } } + bool overflow = false; for (; i < len; i++) { + machine_int_t old_val = int_val; if (unichar_isdigit(str[i]) && str[i] - '0' < base) { int_val = base * int_val + str[i] - '0'; } else if (base == 16 && 'a' <= str[i] && str[i] <= 'f') { @@ -225,10 +233,17 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) { small_int = false; break; } + if (int_val < old_val) { + // If new value became less than previous, it's overflow + overflow = true; + } else if ((old_val ^ int_val) & WORD_MSBIT_HIGH) { + // If signed number changed sign - it's overflow + overflow = true; + } } if (dec) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_DECIMAL, qstr_from_strn_copy(str, len)); - } else if (small_int && MP_FIT_SMALL_INT(int_val)) { + } else if (small_int && !overflow && MP_FIT_SMALL_INT(int_val)) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, int_val); } else { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_INTEGER, qstr_from_strn_copy(str, len)); @@ -251,23 +266,31 @@ static void push_result_rule(parser_t *parser, const rule_t *rule, int num_args) push_result_node(parser, (mp_parse_node_t)pn); } -mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { - parser_t *parser = m_new(parser_t, 1); +mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr *exc_id_out, const char **exc_msg_out) { + + // allocate memory for the parser and its stacks + + parser_t *parser = m_new_obj(parser_t); + parser->rule_stack_alloc = 64; parser->rule_stack_top = 0; parser->rule_stack = m_new(rule_stack_t, parser->rule_stack_alloc); - parser->result_stack = m_new(mp_parse_node_t, 1000); + parser->result_stack_alloc = 64; parser->result_stack_top = 0; + parser->result_stack = m_new(mp_parse_node_t, parser->result_stack_alloc); + // work out the top-level rule to use, and push it on the stack int top_level_rule; switch (input_kind) { case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break; - //case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break; + case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break; default: top_level_rule = RULE_file_input; } push_rule(parser, rules[top_level_rule], 0); + // parse! + uint n, i; bool backtrack = false; const rule_t *rule; @@ -558,22 +581,39 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { //printf("--------------\n"); //result_stack_show(parser); - assert(parser->result_stack_top == 1); - //printf("maximum depth: %d\n", parser->rule_stack_alloc); + //printf("rule stack alloc: %d\n", parser->rule_stack_alloc); + //printf("result stack alloc: %d\n", parser->result_stack_alloc); //printf("number of parse nodes allocated: %d\n", num_parse_nodes_allocated); - return parser->result_stack[0]; + + // get the root parse node that we created + assert(parser->result_stack_top == 1); + mp_parse_node_t result = parser->result_stack[0]; + +finished: + // free the memory that we don't need anymore + m_del(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc); + m_del(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc); + m_del_obj(parser_t, parser); + + // return the result + return result; syntax_error: if (mp_lexer_is_kind(lex, MP_TOKEN_INDENT)) { - mp_lexer_show_error_pythonic(lex, "IndentationError: unexpected indent"); + *exc_id_out = MP_QSTR_IndentationError; + *exc_msg_out = "unexpected indent"; } else if (mp_lexer_is_kind(lex, MP_TOKEN_DEDENT_MISMATCH)) { - mp_lexer_show_error_pythonic(lex, "IndentationError: unindent does not match any outer indentation level"); + *exc_id_out = MP_QSTR_IndentationError; + *exc_msg_out = "unindent does not match any outer indentation level"; } else { - mp_lexer_show_error_pythonic(lex, "syntax error:"); + *exc_id_out = MP_QSTR_SyntaxError; + *exc_msg_out = "invalid syntax"; #ifdef USE_RULE_NAME - mp_lexer_show_error(lex, rule->rule_name); -#endif + // debugging: print the rule name that failed and the token + mp_lexer_show_error_pythonic(lex, rule->rule_name); mp_token_show(mp_lexer_cur(lex)); +#endif } - return MP_PARSE_NODE_NULL; + result = MP_PARSE_NODE_NULL; + goto finished; } diff --git a/py/parse.h b/py/parse.h index 7326243ea4..be2073ae5d 100644 --- a/py/parse.h +++ b/py/parse.h @@ -62,4 +62,5 @@ typedef enum { MP_PARSE_EVAL_INPUT, } mp_parse_input_kind_t; -mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind); +// returns MP_PARSE_NODE_NULL on error, and then exc_id_out and exc_msg_out are valid +mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr *exc_id_out, const char **exc_msg_out); @@ -78,12 +78,15 @@ PY_O_BASENAME = \ objclosure.o \ objcomplex.o \ objdict.o \ + objenumerate.o \ objexcept.o \ + objfilter.o \ objfloat.o \ objfun.o \ objgenerator.o \ objint.o \ objlist.o \ + objmap.o \ objmodule.o \ objnone.o \ objrange.o \ @@ -95,9 +98,11 @@ PY_O_BASENAME = \ stream.o \ builtin.o \ builtinimport.o \ + builtineval.o \ vm.o \ showbc.o \ repl.o \ + objzip.o \ # prepend the build destination prefix to the py object files diff --git a/py/runtime.c b/py/runtime.c index b982ee32d0..e1e9e31cc7 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -90,13 +90,14 @@ void rt_init(void) { mp_map_add_qstr(&map_builtins, MP_QSTR_SyntaxError, mp_obj_new_exception(MP_QSTR_SyntaxError)); mp_map_add_qstr(&map_builtins, MP_QSTR_ValueError, mp_obj_new_exception(MP_QSTR_ValueError)); mp_map_add_qstr(&map_builtins, MP_QSTR_OSError, mp_obj_new_exception(MP_QSTR_OSError)); + mp_map_add_qstr(&map_builtins, MP_QSTR_AssertionError, mp_obj_new_exception(MP_QSTR_AssertionError)); // built-in objects mp_map_add_qstr(&map_builtins, MP_QSTR_Ellipsis, mp_const_ellipsis); // built-in core functions mp_map_add_qstr(&map_builtins, MP_QSTR___build_class__, (mp_obj_t)&mp_builtin___build_class___obj); - mp_map_add_qstr(&map_builtins, MP_QSTR___repl_print__, rt_make_function_1(mp_builtin___repl_print__)); + mp_map_add_qstr(&map_builtins, MP_QSTR___repl_print__, (mp_obj_t)&mp_builtin___repl_print___obj); // built-in types mp_map_add_qstr(&map_builtins, MP_QSTR_bool, (mp_obj_t)&bool_type); @@ -104,35 +105,43 @@ void rt_init(void) { mp_map_add_qstr(&map_builtins, MP_QSTR_complex, (mp_obj_t)&complex_type); #endif mp_map_add_qstr(&map_builtins, MP_QSTR_dict, (mp_obj_t)&dict_type); + mp_map_add_qstr(&map_builtins, MP_QSTR_enumerate, (mp_obj_t)&enumerate_type); + mp_map_add_qstr(&map_builtins, MP_QSTR_filter, (mp_obj_t)&filter_type); #if MICROPY_ENABLE_FLOAT mp_map_add_qstr(&map_builtins, MP_QSTR_float, (mp_obj_t)&float_type); #endif mp_map_add_qstr(&map_builtins, MP_QSTR_int, (mp_obj_t)&int_type); mp_map_add_qstr(&map_builtins, MP_QSTR_list, (mp_obj_t)&list_type); + mp_map_add_qstr(&map_builtins, MP_QSTR_map, (mp_obj_t)&map_type); mp_map_add_qstr(&map_builtins, MP_QSTR_set, (mp_obj_t)&set_type); mp_map_add_qstr(&map_builtins, MP_QSTR_tuple, (mp_obj_t)&tuple_type); mp_map_add_qstr(&map_builtins, MP_QSTR_type, (mp_obj_t)&mp_const_type); - - // built-in user functions; TODO covert all to &mp_builtin_xxx's - mp_map_add_qstr(&map_builtins, MP_QSTR_abs, rt_make_function_1(mp_builtin_abs)); - mp_map_add_qstr(&map_builtins, MP_QSTR_all, rt_make_function_1(mp_builtin_all)); - mp_map_add_qstr(&map_builtins, MP_QSTR_any, rt_make_function_1(mp_builtin_any)); - mp_map_add_qstr(&map_builtins, MP_QSTR_callable, rt_make_function_1(mp_builtin_callable)); - mp_map_add_qstr(&map_builtins, MP_QSTR_chr, rt_make_function_1(mp_builtin_chr)); - mp_map_add_qstr(&map_builtins, MP_QSTR_divmod, rt_make_function_2(mp_builtin_divmod)); + mp_map_add_qstr(&map_builtins, MP_QSTR_zip, (mp_obj_t)&zip_type); + + // built-in user functions + mp_map_add_qstr(&map_builtins, MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_eval, (mp_obj_t)&mp_builtin_eval_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_hash, (mp_obj_t)&mp_builtin_hash_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_isinstance, (mp_obj_t)&mp_builtin_isinstance_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_issubclass, (mp_obj_t)&mp_builtin_issubclass_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_iter, (mp_obj_t)&mp_builtin_iter_obj); - mp_map_add_qstr(&map_builtins, MP_QSTR_len, rt_make_function_1(mp_builtin_len)); - mp_map_add_qstr(&map_builtins, MP_QSTR_max, rt_make_function_var(1, mp_builtin_max)); - mp_map_add_qstr(&map_builtins, MP_QSTR_min, rt_make_function_var(1, mp_builtin_min)); + mp_map_add_qstr(&map_builtins, MP_QSTR_len, (mp_obj_t)&mp_builtin_len_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_max, (mp_obj_t)&mp_builtin_max_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_min, (mp_obj_t)&mp_builtin_min_obj); mp_map_add_qstr(&map_builtins, MP_QSTR_next, (mp_obj_t)&mp_builtin_next_obj); - mp_map_add_qstr(&map_builtins, MP_QSTR_ord, rt_make_function_1(mp_builtin_ord)); - mp_map_add_qstr(&map_builtins, MP_QSTR_pow, rt_make_function_var(2, mp_builtin_pow)); - mp_map_add_qstr(&map_builtins, MP_QSTR_print, rt_make_function_var(0, mp_builtin_print)); - mp_map_add_qstr(&map_builtins, MP_QSTR_range, rt_make_function_var(1, mp_builtin_range)); - mp_map_add_qstr(&map_builtins, MP_QSTR_sum, rt_make_function_var(1, mp_builtin_sum)); + mp_map_add_qstr(&map_builtins, MP_QSTR_ord, (mp_obj_t)&mp_builtin_ord_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_pow, (mp_obj_t)&mp_builtin_pow_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_print, (mp_obj_t)&mp_builtin_print_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_range, (mp_obj_t)&mp_builtin_range_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_repr, (mp_obj_t)&mp_builtin_repr_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_sorted, (mp_obj_t)&mp_builtin_sorted_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_sum, (mp_obj_t)&mp_builtin_sum_obj); + mp_map_add_qstr(&map_builtins, MP_QSTR_str, (mp_obj_t)&mp_builtin_str_obj); next_unique_code_id = 1; // 0 indicates "no code" unique_codes_alloc = 0; @@ -267,10 +276,6 @@ void rt_assign_inline_asm_code(int unique_code_id, void *fun, uint len, int n_ar #endif } -static bool fit_small_int(mp_small_int_t o) { - return true; -} - int rt_is_true(mp_obj_t arg) { DEBUG_OP_printf("is true %p\n", arg); if (MP_OBJ_IS_SMALL_INT(arg)) { @@ -435,13 +440,10 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) { case RT_UNARY_OP_INVERT: val = ~val; break; default: assert(0); val = 0; } - if (fit_small_int(val)) { + if (MP_OBJ_FITS_SMALL_INT(val)) { return MP_OBJ_NEW_SMALL_INT(val); - } else { - // TODO make a bignum - assert(0); - return mp_const_none; } + return mp_obj_new_int(val); } else { // will be an object (small ints are caught in previous if) mp_obj_base_t *o = arg; if (o->type->unary_op != NULL) { @@ -467,6 +469,18 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { // then fail // note that list does not implement + or +=, so that inplace_concat is reached first for += + // deal with is, is not + if (op == RT_COMPARE_OP_IS) { + // TODO: may need to handle strings specially, CPython appears to + // assume all strings are interned (so "is" == "==" for strings) + return MP_BOOL(lhs == rhs); + } + if (op == RT_COMPARE_OP_IS_NOT) { + // TODO: may need to handle strings specially, CPython appears to + // assume all strings are interned (so "is" == "==" for strings) + return MP_BOOL(lhs != rhs); + } + // deal with == and != for all types if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) { if (mp_obj_equal(lhs, rhs)) { @@ -550,32 +564,67 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { default: assert(0); } - if (fit_small_int(lhs_val)) { + // TODO: We just should make mp_obj_new_int() inline and use that + if (MP_OBJ_FITS_SMALL_INT(lhs_val)) { return MP_OBJ_NEW_SMALL_INT(lhs_val); } - // TODO: return long int - assert(0); + return mp_obj_new_int(lhs_val); } else if (MP_OBJ_IS_TYPE(rhs, &float_type)) { return mp_obj_float_binary_op(op, lhs_val, rhs); } else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) { return mp_obj_complex_binary_op(op, lhs_val, 0, rhs); } - } else { - if (MP_OBJ_IS_OBJ(lhs)) { - mp_obj_base_t *o = lhs; + } + + /* deal with `in` and `not in` + * + * NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch + * needs to go below + */ + if (op == RT_COMPARE_OP_IN || op == RT_COMPARE_OP_NOT_IN) { + if (!MP_OBJ_IS_SMALL_INT(rhs)) { + mp_obj_base_t *o = rhs; if (o->type->binary_op != NULL) { - mp_obj_t result = o->type->binary_op(op, lhs, rhs); - if (result != NULL) { - return result; + mp_obj_t res = o->type->binary_op(op, rhs, lhs); + if (res != NULL) { + return res; } } + if (o->type->getiter != NULL) { + /* second attempt, walk the iterator */ + mp_obj_t next = NULL; + mp_obj_t iter = rt_getiter(rhs); + while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { + if (mp_obj_equal(next, lhs)) { + return MP_BOOL(op == RT_COMPARE_OP_IN); + } + } + return MP_BOOL(op != RT_COMPARE_OP_IN); + } + } + + nlr_jump(mp_obj_new_exception_msg_varg( + MP_QSTR_TypeError, "'%s' object is not iterable", + mp_obj_get_type_str(rhs))); + return mp_const_none; + } + + if (MP_OBJ_IS_OBJ(lhs)) { + mp_obj_base_t *o = lhs; + if (o->type->binary_op != NULL) { + mp_obj_t result = o->type->binary_op(op, lhs, rhs); + if (result != NULL) { + return result; + } } + // TODO implement dispatch for reverse binary ops } // TODO specify in error message what the operator is nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unsupported operand types for binary operator: '%s', '%s'", mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs))); + return mp_const_none; } mp_obj_t rt_make_function_from_id(int unique_code_id) { @@ -593,12 +642,7 @@ mp_obj_t rt_make_function_from_id(int unique_code_id) { fun = mp_obj_new_fun_bc(c->n_args, c->n_locals + c->n_stack, c->u_byte.code); break; case MP_CODE_NATIVE: - switch (c->n_args) { - case 0: fun = rt_make_function_0(c->u_native.fun); break; - case 1: fun = rt_make_function_1((mp_fun_1_t)c->u_native.fun); break; - case 2: fun = rt_make_function_2((mp_fun_2_t)c->u_native.fun); break; - default: assert(0); fun = mp_const_none; - } + fun = rt_make_function_n(c->n_args, c->u_native.fun); break; case MP_CODE_INLINE_ASM: fun = mp_obj_new_fun_asm(c->n_args, c->u_inline_asm.fun); diff --git a/py/runtime.h b/py/runtime.h index ac53e14110..32cb47684f 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -12,10 +12,8 @@ void rt_store_global(qstr qstr, mp_obj_t obj); mp_obj_t rt_unary_op(int op, mp_obj_t arg); mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t rt_make_function_from_id(int unique_code_id); -mp_obj_t rt_make_function_0(mp_fun_0_t f); -mp_obj_t rt_make_function_1(mp_fun_1_t f); -mp_obj_t rt_make_function_2(mp_fun_2_t f); -mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t f); +mp_obj_t rt_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments +mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t fun); mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple); mp_obj_t rt_call_function_0(mp_obj_t fun); diff --git a/py/stream.c b/py/stream.c index f883efcd25..e70d365681 100644 --- a/py/stream.c +++ b/py/stream.c @@ -51,5 +51,91 @@ static mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) { } } +// TODO: should be in mpconfig.h +#define READ_SIZE 256 +static mp_obj_t stream_readall(mp_obj_t self_in) { + struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in; + if (o->type->stream_p.read == NULL) { + // CPython: io.UnsupportedOperation, OSError subclass + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported")); + } + + int total_size = 0; + vstr_t *vstr = vstr_new_size(READ_SIZE); + char *buf = vstr_str(vstr); + char *p = buf; + int error; + int current_read = READ_SIZE; + while (true) { + machine_int_t out_sz = o->type->stream_p.read(self_in, p, current_read, &error); + if (out_sz == -1) { + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); + } + if (out_sz == 0) { + break; + } + total_size += out_sz; + if (out_sz < current_read) { + current_read -= out_sz; + p += out_sz; + } else { + current_read = READ_SIZE; + p = vstr_extend(vstr, current_read); + if (p == NULL) { + // TODO + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError/*MP_QSTR_RuntimeError*/, "Out of memory")); + } + } + } + vstr_set_size(vstr, total_size + 1); // TODO: for \0 + buf[total_size] = 0; + return mp_obj_new_str(qstr_from_str_take(buf, total_size + 1)); +} + +// Unbuffered, inefficient implementation of readline() for raw I/O files. +static mp_obj_t stream_unbuffered_readline(int n_args, const mp_obj_t *args) { + struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; + if (o->type->stream_p.read == NULL) { + // CPython: io.UnsupportedOperation, OSError subclass + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported")); + } + + machine_int_t max_size = -1; + if (n_args > 1) { + max_size = MP_OBJ_SMALL_INT_VALUE(args[1]); + } + + vstr_t *vstr; + if (max_size != -1) { + vstr = vstr_new_size(max_size + 1); // TODO: \0 + } else { + vstr = vstr_new(); + } + + int error; + while (max_size == -1 || max_size-- != 0) { + char *p = vstr_add_len(vstr, 1); + if (p == NULL) { + // TODO + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError/*MP_QSTR_RuntimeError*/, "Out of memory")); + } + + machine_int_t out_sz = o->type->stream_p.read(o, p, 1, &error); + if (out_sz == -1) { + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); + } + if (out_sz == 0 || *p == '\n') { + break; + } + } + // TODO: \0 + vstr_add_byte(vstr, 0); + vstr_shrink(vstr); + return mp_obj_new_str(qstr_from_str_take(vstr_str(vstr), vstr_len(vstr))); +} + + MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_read_obj, stream_read); +MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline); MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write); diff --git a/py/stream.h b/py/stream.h index 8a579b7621..58e8072549 100644 --- a/py/stream.h +++ b/py/stream.h @@ -1,2 +1,4 @@ extern const mp_obj_fun_native_t mp_stream_read_obj; +extern const mp_obj_fun_native_t mp_stream_readall_obj; +extern const mp_obj_fun_native_t mp_stream_unbuffered_readline_obj; extern const mp_obj_fun_native_t mp_stream_write_obj; diff --git a/py/strtonum.c b/py/strtonum.c index 109ea1123b..02c1506683 100644 --- a/py/strtonum.c +++ b/py/strtonum.c @@ -10,7 +10,6 @@ #include "nlr.h" #include "obj.h" - long strtonum(const char *restrict s, int base) { int c, neg = 0; const char *p = s; @@ -33,6 +32,7 @@ long strtonum(const char *restrict s, int base) { } // find real radix base, and strip preced '0x', '0o' and '0b' + // TODO somehow merge with similar code in parse.c if ((base == 0 || base == 16) && c == '0') { c = *(p++); if ((c | 32) == 'x') { diff --git a/py/strtonum.h b/py/strtonum.h deleted file mode 100644 index 03565cca14..0000000000 --- a/py/strtonum.h +++ /dev/null @@ -1 +0,0 @@ -long strtonum(const char *restrict s, int base); @@ -440,10 +440,17 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t ** case MP_BC_CALL_FUNCTION: DECODE_UINT; - assert((unum & 0xff00) == 0); // n_keyword - unum &= 0xff; // n_positional - sp += unum; - *sp = rt_call_function_n(*sp, unum, sp - unum); + if ((unum & 0xff00) == 0) { + // no keywords + unum &= 0xff; // n_positional + sp += unum; + *sp = rt_call_function_n(*sp, unum, sp - unum); + } else { + // keywords + int argsize = (unum & 0xff) + ((unum >> 7) & 0x1fe); + sp += argsize; + *sp = rt_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp - argsize); + } break; case MP_BC_CALL_METHOD: @@ -6,8 +6,8 @@ // returned value is always at least 1 greater than argument #define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8) -void vstr_init(vstr_t *vstr) { - vstr->alloc = 32; +void vstr_init(vstr_t *vstr, int alloc) { + vstr->alloc = alloc; vstr->len = 0; vstr->buf = m_new(char, vstr->alloc); if (vstr->buf == NULL) { @@ -28,7 +28,16 @@ vstr_t *vstr_new(void) { if (vstr == NULL) { return NULL; } - vstr_init(vstr); + vstr_init(vstr, 32); + return vstr; +} + +vstr_t *vstr_new_size(int alloc) { + vstr_t *vstr = m_new(vstr_t, 1); + if (vstr == NULL) { + return NULL; + } + vstr_init(vstr, alloc); return vstr; } @@ -63,6 +72,36 @@ int vstr_len(vstr_t *vstr) { return vstr->len; } +// Extend vstr strictly to by requested size, return pointer to newly added chunk +char *vstr_extend(vstr_t *vstr, int size) { + char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size); + if (new_buf == NULL) { + vstr->had_error = true; + return NULL; + } + char *p = new_buf + vstr->alloc; + vstr->alloc += size; + vstr->buf = new_buf; + return p; +} + +// Shrink vstr to be given size +bool vstr_set_size(vstr_t *vstr, int size) { + char *new_buf = m_renew(char, vstr->buf, vstr->alloc, size); + if (new_buf == NULL) { + vstr->had_error = true; + return false; + } + vstr->buf = new_buf; + vstr->alloc = vstr->len = size; + return true; +} + +// Shrink vstr allocation to its actual length +bool vstr_shrink(vstr_t *vstr) { + return vstr_set_size(vstr, vstr->len); +} + bool vstr_ensure_extra(vstr_t *vstr, int size) { if (vstr->len + size + 1 > vstr->alloc) { int new_alloc = ROUND_ALLOC((vstr->len + size + 1) * 2); diff --git a/stm/Makefile b/stm/Makefile index 2fecd03bad..d4dbd960a6 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -33,6 +33,7 @@ CFLAGS += -Os -DNDEBUG endif LDFLAGS = --nostdlib -T stm32f405.ld +LIBS = $(shell $(CC) -print-libgcc-file-name) SRC_C = \ main.c \ @@ -57,6 +58,7 @@ SRC_C = \ pybwlan.c \ i2c.c \ usrsw.c \ + adc.c \ SRC_S = \ startup_stm32f40xx.s \ @@ -100,11 +102,20 @@ SRC_STM = \ usbd_storage_msd.c \ stm324x7i_eval.c \ stm324x7i_eval_sdio_sd.c \ + stm32f4xx_adc.c \ #SRC_STM_OTG = \ # usb_hcd.c \ # usb_hcd_int.c \ # usb_otg.c \ +# usbh_core.c \ +# usbh_hcs.c \ +# usbh_stdreq.c \ +# usbh_ioreq.c \ +# usbh_usr.c \ +# usbh_hid_core.c \ +# usbh_hid_mouse.c \ +# usbh_hid_keybd.c \ SRC_CC3K = \ cc3000_common.c \ @@ -135,7 +146,7 @@ $(BUILD)/flash1.bin: $(BUILD)/flash.elf $(BUILD)/flash.elf: $(OBJ) $(ECHO) "LINK $@" - $(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) + $(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(Q)$(SIZE) $@ $(BUILD)/%.o: %.s diff --git a/stm/adc.c b/stm/adc.c new file mode 100644 index 0000000000..1f666c2718 --- /dev/null +++ b/stm/adc.c @@ -0,0 +1,304 @@ +#include <stdio.h> +#include <stm32f4xx_rcc.h> +#include <stm32f4xx_gpio.h> +#include <stm32f4xx_adc.h> + +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "adc.h" + +/* ADC defintions */ +#define ADCx (ADC1) +#define ADCx_CLK (RCC_APB2Periph_ADC1) +#define ADC_NUM_CHANNELS (16) + +/* Internally connected ADC channels Temp/VBAT/VREF*/ +#if defined (STM32F40XX) || defined(STM32F41XX) +#define ADC_TEMP_CHANNEL (16) +#define ADC_VBAT_CHANNEL (18) +#define ADC_VREF_CHANNEL (17) +#elif defined (STM32F42XX) || defined(STM32F43XX) +#define ADC_TEMP_CHANNEL (18) +#define ADC_VBAT_CHANNEL (18) /* same channel as TEMP */ +#define ADC_VREF_CHANNEL (17) +#endif + +/* Core temperature sensor definitions */ +#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */ +#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */ + +/* VBAT divider */ +#if defined (STM32F40XX) || defined(STM32F41XX) +#define VBAT_DIV (2) +#elif defined (STM32F42XX) || defined(STM32F43XX) +#define VBAT_DIV (4) +#endif + +/* GPIO struct */ +typedef struct { + GPIO_TypeDef* port; + uint32_t pin; +} gpio_t; + +/* ADC GPIOs */ +static gpio_t adc_gpio[] = { + {GPIOA, GPIO_Pin_0}, /* ADC123_IN0 */ + {GPIOA, GPIO_Pin_1}, /* ADC123_IN1 */ + {GPIOA, GPIO_Pin_2}, /* ADC123_IN2 */ + {GPIOA, GPIO_Pin_3}, /* ADC123_IN3 */ + {GPIOA, GPIO_Pin_4}, /* ADC12_IN4 */ + {GPIOA, GPIO_Pin_5}, /* ADC12_IN5 */ + {GPIOA, GPIO_Pin_6}, /* ADC12_IN6 */ + {GPIOA, GPIO_Pin_7}, /* ADC12_IN7 */ + {GPIOB, GPIO_Pin_0}, /* ADC12_IN8 */ + {GPIOB, GPIO_Pin_1}, /* ADC12_IN9 */ + {GPIOC, GPIO_Pin_0}, /* ADC123_IN10 */ + {GPIOC, GPIO_Pin_1}, /* ADC123_IN11 */ + {GPIOC, GPIO_Pin_2}, /* ADC123_IN12 */ + {GPIOC, GPIO_Pin_3}, /* ADC123_IN13 */ + {GPIOC, GPIO_Pin_4}, /* ADC12_IN14 */ + {GPIOC, GPIO_Pin_5}, /* ADC12_IN15 */ + +}; + +void adc_init(uint32_t resolution) { + ADC_InitTypeDef ADC_InitStructure; + GPIO_InitTypeDef GPIO_InitStructure; + ADC_CommonInitTypeDef ADC_CommonInitStructure; + + /* Enable ADCx, DMA and GPIO clocks */ +#if 0 + /* GPIO clocks enabled in main */ + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | + RCC_AHB1Periph_GPIOB | + RCC_AHB1Periph_GPIOC, ENABLE); +#endif + RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE); + + /* ADC Common Init */ + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInit(&ADC_CommonInitStructure); + + /* Configure ADC GPIOs */ + for (int i=0; i<ADC_NUM_CHANNELS; i++) { + GPIO_InitStructure.GPIO_Pin = adc_gpio[i].pin; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(adc_gpio[i].port, &GPIO_InitStructure); + } + + /* ADCx Init */ +// ADC_DeInit(); + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADCx, &ADC_InitStructure); + + /* Enable ADCx */ + ADC_Cmd(ADCx, ENABLE); + + /* Enable VBAT/VREF monitor */ + ADC_VBATCmd(ENABLE); + + /* Enable temperature sensor */ + ADC_TempSensorVrefintCmd(ENABLE); +} + +uint32_t adc_read_channel(int channel) +{ + int timeout = 10000; + + if (channel > (ADC_NUM_CHANNELS-1)) { + return 0; + } + + /* ADC regular channel config ADC/Channel/SEQ Rank/Sample time */ + ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime_15Cycles); + + /* Start ADC single conversion */ + ADC_SoftwareStartConv(ADCx); + + /* Wait for conversion to be complete*/ + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { + } + + /* ADC conversion timed out */ + if (timeout == 0) { + return 0; + } + + /* Return converted data */ + return ADC_GetConversionValue(ADCx); +} + +int adc_read_core_temp() +{ + int timeout = 10000; + + /* ADC temperature sensor channel config ADC/Channel/SEQ Rank/Sample time */ + /* Note: sample time must be higher than minimum sample time */ + ADC_RegularChannelConfig(ADCx, ADC_TEMP_CHANNEL, 1, ADC_SampleTime_480Cycles); + + /* Start ADC single conversion */ + ADC_SoftwareStartConv(ADCx); + + /* Wait for conversion to be complete*/ + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { + } + + /* ADC conversion timed out */ + if (timeout == 0) { + return 0; + } + + /* Convert ADC reading to temperature */ + /* Temperature formula from datasheet P.411 */ + return ((ADC_GetConversionValue(ADCx) - CORE_TEMP_V25) / CORE_TEMP_AVG_SLOPE) + 25; +} + +float adc_read_core_vbat() +{ + int timeout = 10000; + + /* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */ + /* Note: sample time must be higher than minimum sample time */ + ADC_RegularChannelConfig(ADCx, ADC_VBAT_CHANNEL, 1, ADC_SampleTime_144Cycles); + + /* Start ADC single conversion */ + ADC_SoftwareStartConv(ADCx); + + /* Wait for conversion to be complete */ + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { + } + + /* ADC conversion timed out */ + if (timeout == 0) { + return 0; + } + + /* Convert ADC reading to voltage, VBAT pin is + internally connected to a bridge divider by VBAT_DIV */ + return ADC_GetConversionValue(ADCx)*VBAT_DIV/4096.0f*3.3f; +} + +float adc_read_core_vref() +{ + int timeout = 10000; + + /* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */ + /* Note: sample time must be higher than minimum sample time */ + ADC_RegularChannelConfig(ADCx, ADC_VREF_CHANNEL, 1, ADC_SampleTime_112Cycles); + + /* Start ADC single conversion */ + ADC_SoftwareStartConv(ADCx); + + /* Wait for conversion to be complete*/ + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { + } + + /* ADC conversion timed out */ + if (timeout == 0) { + return 0; + } + + /* Convert ADC reading to voltage */ + return ADC_GetConversionValue(ADCx)/4096.0f*3.3f; +} + +/******************************************************************************/ +/* Micro Python bindings */ + +typedef struct _pyb_adc_obj_t { + mp_obj_base_t base; + int adc_id; + bool is_enabled; +} pyb_adc_obj_t; + +static mp_obj_t adc_obj_read_channel(mp_obj_t self_in, mp_obj_t channel) { + mp_obj_t ret = mp_const_none; + pyb_adc_obj_t *self = self_in; + + if (self->is_enabled) { + uint32_t chan = mp_obj_get_int(channel); + uint32_t data = adc_read_channel(chan); + ret = mp_obj_new_int(data); + } + return ret; +} + +static mp_obj_t adc_obj_read_core_temp(mp_obj_t self_in) { + mp_obj_t ret = mp_const_none; + pyb_adc_obj_t *self = self_in; + + if (self->is_enabled) { + int data = adc_read_core_temp(); + ret = mp_obj_new_int(data); + } + return ret; +} + +static mp_obj_t adc_obj_read_core_vbat(mp_obj_t self_in) { + mp_obj_t ret = mp_const_none; + pyb_adc_obj_t *self = self_in; + + if (self->is_enabled) { + float data = adc_read_core_vbat(); + ret = mp_obj_new_float(data); + } + return ret; +} + +static mp_obj_t adc_obj_read_core_vref(mp_obj_t self_in) { + mp_obj_t ret = mp_const_none; + pyb_adc_obj_t *self = self_in; + + if (self->is_enabled) { + float data = adc_read_core_vref(); + ret = mp_obj_new_float(data); + } + return ret; +} + +static void adc_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + pyb_adc_obj_t *self = self_in; + print(env, "<ADC %lu>", self->adc_id); +} + +static MP_DEFINE_CONST_FUN_OBJ_2(adc_obj_read_channel_obj, adc_obj_read_channel); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_temp_obj, adc_obj_read_core_temp); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vbat_obj, adc_obj_read_core_vbat); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vref_obj, adc_obj_read_core_vref); + +static const mp_method_t adc_methods[] = { + { "read_channel", &adc_obj_read_channel_obj}, + { "read_core_temp", &adc_obj_read_core_temp_obj}, + { "read_core_vbat", &adc_obj_read_core_vbat_obj}, + { "read_core_vref", &adc_obj_read_core_vref_obj}, + { NULL, NULL }, +}; + +static const mp_obj_type_t adc_obj_type = { + { &mp_const_type }, + "ADC", + .print = adc_obj_print, + .methods = adc_methods, +}; + +mp_obj_t pyb_ADC(mp_obj_t resolution) { + /* init ADC */ + adc_init(mp_obj_get_int(resolution)); + + pyb_adc_obj_t *o = m_new_obj(pyb_adc_obj_t); + o->base.type = &adc_obj_type; + o->adc_id = 1; + o->is_enabled = true; + return o; +} diff --git a/stm/adc.h b/stm/adc.h new file mode 100644 index 0000000000..5805aef42c --- /dev/null +++ b/stm/adc.h @@ -0,0 +1 @@ +mp_obj_t pyb_ADC(mp_obj_t resolution); diff --git a/stm/audio.c b/stm/audio.c index 34adefbcd6..e2aa32b9fc 100644 --- a/stm/audio.c +++ b/stm/audio.c @@ -91,8 +91,8 @@ void audio_init(void) { // Python interface mp_obj_t m = mp_obj_new_module(qstr_from_str_static("audio")); - rt_store_attr(m, qstr_from_str_static("dac"), rt_make_function_1(pyb_audio_dac)); - rt_store_attr(m, qstr_from_str_static("is_full"), rt_make_function_0(pyb_audio_is_full)); - rt_store_attr(m, qstr_from_str_static("fill"), rt_make_function_1(pyb_audio_fill)); + rt_store_attr(m, qstr_from_str_static("dac"), rt_make_function_n(1, pyb_audio_dac)); + rt_store_attr(m, qstr_from_str_static("is_full"), rt_make_function_n(0, pyb_audio_is_full)); + rt_store_attr(m, qstr_from_str_static("fill"), rt_make_function_n(1, pyb_audio_fill)); rt_store_name(qstr_from_str_static("audio"), m); } @@ -220,13 +220,13 @@ void lcd_init(void) { // Python interface mp_obj_t m = mp_obj_new_module(qstr_from_str_static("lcd")); - rt_store_attr(m, qstr_from_str_static("lcd8"), rt_make_function_2(lcd_draw_pixel_8)); - rt_store_attr(m, qstr_from_str_static("clear"), rt_make_function_0(lcd_pix_clear)); - rt_store_attr(m, qstr_from_str_static("get"), rt_make_function_2(lcd_pix_get)); - rt_store_attr(m, qstr_from_str_static("set"), rt_make_function_2(lcd_pix_set)); - rt_store_attr(m, qstr_from_str_static("reset"), rt_make_function_2(lcd_pix_reset)); - rt_store_attr(m, qstr_from_str_static("show"), rt_make_function_0(lcd_pix_show)); - rt_store_attr(m, qstr_from_str_static("text"), rt_make_function_1(lcd_print)); + rt_store_attr(m, qstr_from_str_static("lcd8"), rt_make_function_n(2, lcd_draw_pixel_8)); + rt_store_attr(m, qstr_from_str_static("clear"), rt_make_function_n(0, lcd_pix_clear)); + rt_store_attr(m, qstr_from_str_static("get"), rt_make_function_n(2, lcd_pix_get)); + rt_store_attr(m, qstr_from_str_static("set"), rt_make_function_n(2, lcd_pix_set)); + rt_store_attr(m, qstr_from_str_static("reset"), rt_make_function_n(2, lcd_pix_reset)); + rt_store_attr(m, qstr_from_str_static("show"), rt_make_function_n(0, lcd_pix_show)); + rt_store_attr(m, qstr_from_str_static("text"), rt_make_function_n(1, lcd_print)); rt_store_name(qstr_from_str_static("lcd"), m); } diff --git a/stm/lib/stm32f4xx_adc.c b/stm/lib/stm32f4xx_adc.c new file mode 100644 index 0000000000..eacc6b51f1 --- /dev/null +++ b/stm/lib/stm32f4xx_adc.c @@ -0,0 +1,1746 @@ +/**
+ ******************************************************************************
+ * @file stm32f4xx_adc.c
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 08-November-2013
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Analog to Digital Convertor (ADC) peripheral:
+ * + Initialization and Configuration (in addition to ADC multi mode
+ * selection)
+ * + Analog Watchdog configuration
+ * + Temperature Sensor & Vrefint (Voltage Reference internal) & VBAT
+ * management
+ * + Regular Channels Configuration
+ * + Regular Channels DMA Configuration
+ * + Injected channels Configuration
+ * + Interrupts and flags management
+ *
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ (#) Enable the ADC interface clock using
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCx, ENABLE);
+
+ (#) ADC pins configuration
+ (++) Enable the clock for the ADC GPIOs using the following function:
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
+ (++) Configure these ADC pins in analog mode using GPIO_Init();
+
+ (#) Configure the ADC Prescaler, conversion resolution and data
+ alignment using the ADC_Init() function.
+ (#) Activate the ADC peripheral using ADC_Cmd() function.
+
+ *** Regular channels group configuration ***
+ ============================================
+ [..]
+ (+) To configure the ADC regular channels group features, use
+ ADC_Init() and ADC_RegularChannelConfig() functions.
+ (+) To activate the continuous mode, use the ADC_continuousModeCmd()
+ function.
+ (+) To configurate and activate the Discontinuous mode, use the
+ ADC_DiscModeChannelCountConfig() and ADC_DiscModeCmd() functions.
+ (+) To read the ADC converted values, use the ADC_GetConversionValue()
+ function.
+
+ *** Multi mode ADCs Regular channels configuration ***
+ ======================================================
+ [..]
+ (+) Refer to "Regular channels group configuration" description to
+ configure the ADC1, ADC2 and ADC3 regular channels.
+ (+) Select the Multi mode ADC regular channels features (dual or
+ triple mode) using ADC_CommonInit() function and configure
+ the DMA mode using ADC_MultiModeDMARequestAfterLastTransferCmd()
+ functions.
+ (+) Read the ADCs converted values using the
+ ADC_GetMultiModeConversionValue() function.
+
+ *** DMA for Regular channels group features configuration ***
+ =============================================================
+ [..]
+ (+) To enable the DMA mode for regular channels group, use the
+ ADC_DMACmd() function.
+ (+) To enable the generation of DMA requests continuously at the end
+ of the last DMA transfer, use the ADC_DMARequestAfterLastTransferCmd()
+ function.
+
+ *** Injected channels group configuration ***
+ =============================================
+ [..]
+ (+) To configure the ADC Injected channels group features, use
+ ADC_InjectedChannelConfig() and ADC_InjectedSequencerLengthConfig()
+ functions.
+ (+) To activate the continuous mode, use the ADC_continuousModeCmd()
+ function.
+ (+) To activate the Injected Discontinuous mode, use the
+ ADC_InjectedDiscModeCmd() function.
+ (+) To activate the AutoInjected mode, use the ADC_AutoInjectedConvCmd()
+ function.
+ (+) To read the ADC converted values, use the ADC_GetInjectedConversionValue()
+ function.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_adc.h"
+#include "stm32f4xx_rcc.h"
+#include "stm32f4xx_conf.h"
+
+/** @addtogroup STM32F4xx_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup ADC
+ * @brief ADC driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/* ADC DISCNUM mask */
+#define CR1_DISCNUM_RESET ((uint32_t)0xFFFF1FFF)
+
+/* ADC AWDCH mask */
+#define CR1_AWDCH_RESET ((uint32_t)0xFFFFFFE0)
+
+/* ADC Analog watchdog enable mode mask */
+#define CR1_AWDMode_RESET ((uint32_t)0xFF3FFDFF)
+
+/* CR1 register Mask */
+#define CR1_CLEAR_MASK ((uint32_t)0xFCFFFEFF)
+
+/* ADC EXTEN mask */
+#define CR2_EXTEN_RESET ((uint32_t)0xCFFFFFFF)
+
+/* ADC JEXTEN mask */
+#define CR2_JEXTEN_RESET ((uint32_t)0xFFCFFFFF)
+
+/* ADC JEXTSEL mask */
+#define CR2_JEXTSEL_RESET ((uint32_t)0xFFF0FFFF)
+
+/* CR2 register Mask */
+#define CR2_CLEAR_MASK ((uint32_t)0xC0FFF7FD)
+
+/* ADC SQx mask */
+#define SQR3_SQ_SET ((uint32_t)0x0000001F)
+#define SQR2_SQ_SET ((uint32_t)0x0000001F)
+#define SQR1_SQ_SET ((uint32_t)0x0000001F)
+
+/* ADC L Mask */
+#define SQR1_L_RESET ((uint32_t)0xFF0FFFFF)
+
+/* ADC JSQx mask */
+#define JSQR_JSQ_SET ((uint32_t)0x0000001F)
+
+/* ADC JL mask */
+#define JSQR_JL_SET ((uint32_t)0x00300000)
+#define JSQR_JL_RESET ((uint32_t)0xFFCFFFFF)
+
+/* ADC SMPx mask */
+#define SMPR1_SMP_SET ((uint32_t)0x00000007)
+#define SMPR2_SMP_SET ((uint32_t)0x00000007)
+
+/* ADC JDRx registers offset */
+#define JDR_OFFSET ((uint8_t)0x28)
+
+/* ADC CDR register base address */
+#define CDR_ADDRESS ((uint32_t)0x40012308)
+
+/* ADC CCR register Mask */
+#define CR_CLEAR_MASK ((uint32_t)0xFFFC30E0)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup ADC_Private_Functions
+ * @{
+ */
+
+/** @defgroup ADC_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Initialize and configure the ADC Prescaler
+ (+) ADC Conversion Resolution (12bit..6bit)
+ (+) Scan Conversion Mode (multichannel or one channel) for regular group
+ (+) ADC Continuous Conversion Mode (Continuous or Single conversion) for
+ regular group
+ (+) External trigger Edge and source of regular group,
+ (+) Converted data alignment (left or right)
+ (+) The number of ADC conversions that will be done using the sequencer for
+ regular channel group
+ (+) Multi ADC mode selection
+ (+) Direct memory access mode selection for multi ADC mode
+ (+) Delay between 2 sampling phases (used in dual or triple interleaved modes)
+ (+) Enable or disable the ADC peripheral
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes all ADCs peripherals registers to their default reset
+ * values.
+ * @param None
+ * @retval None
+ */
+void ADC_DeInit(void)
+{
+ /* Enable all ADCs reset state */
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, ENABLE);
+
+ /* Release all ADCs from reset state */
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, DISABLE);
+}
+
+/**
+ * @brief Initializes the ADCx peripheral according to the specified parameters
+ * in the ADC_InitStruct.
+ * @note This function is used to configure the global features of the ADC (
+ * Resolution and Data Alignment), however, the rest of the configuration
+ * parameters are specific to the regular channels group (scan mode
+ * activation, continuous mode activation, External trigger source and
+ * edge, number of conversion in the regular channels group sequencer).
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains
+ * the configuration information for the specified ADC peripheral.
+ * @retval None
+ */
+void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)
+{
+ uint32_t tmpreg1 = 0;
+ uint8_t tmpreg2 = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_RESOLUTION(ADC_InitStruct->ADC_Resolution));
+ assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ScanConvMode));
+ assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ContinuousConvMode));
+ assert_param(IS_ADC_EXT_TRIG_EDGE(ADC_InitStruct->ADC_ExternalTrigConvEdge));
+ assert_param(IS_ADC_EXT_TRIG(ADC_InitStruct->ADC_ExternalTrigConv));
+ assert_param(IS_ADC_DATA_ALIGN(ADC_InitStruct->ADC_DataAlign));
+ assert_param(IS_ADC_REGULAR_LENGTH(ADC_InitStruct->ADC_NbrOfConversion));
+
+ /*---------------------------- ADCx CR1 Configuration -----------------*/
+ /* Get the ADCx CR1 value */
+ tmpreg1 = ADCx->CR1;
+
+ /* Clear RES and SCAN bits */
+ tmpreg1 &= CR1_CLEAR_MASK;
+
+ /* Configure ADCx: scan conversion mode and resolution */
+ /* Set SCAN bit according to ADC_ScanConvMode value */
+ /* Set RES bit according to ADC_Resolution value */
+ tmpreg1 |= (uint32_t)(((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8) | \
+ ADC_InitStruct->ADC_Resolution);
+ /* Write to ADCx CR1 */
+ ADCx->CR1 = tmpreg1;
+ /*---------------------------- ADCx CR2 Configuration -----------------*/
+ /* Get the ADCx CR2 value */
+ tmpreg1 = ADCx->CR2;
+
+ /* Clear CONT, ALIGN, EXTEN and EXTSEL bits */
+ tmpreg1 &= CR2_CLEAR_MASK;
+
+ /* Configure ADCx: external trigger event and edge, data alignment and
+ continuous conversion mode */
+ /* Set ALIGN bit according to ADC_DataAlign value */
+ /* Set EXTEN bits according to ADC_ExternalTrigConvEdge value */
+ /* Set EXTSEL bits according to ADC_ExternalTrigConv value */
+ /* Set CONT bit according to ADC_ContinuousConvMode value */
+ tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | \
+ ADC_InitStruct->ADC_ExternalTrigConv |
+ ADC_InitStruct->ADC_ExternalTrigConvEdge | \
+ ((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1));
+
+ /* Write to ADCx CR2 */
+ ADCx->CR2 = tmpreg1;
+ /*---------------------------- ADCx SQR1 Configuration -----------------*/
+ /* Get the ADCx SQR1 value */
+ tmpreg1 = ADCx->SQR1;
+
+ /* Clear L bits */
+ tmpreg1 &= SQR1_L_RESET;
+
+ /* Configure ADCx: regular channel sequence length */
+ /* Set L bits according to ADC_NbrOfConversion value */
+ tmpreg2 |= (uint8_t)(ADC_InitStruct->ADC_NbrOfConversion - (uint8_t)1);
+ tmpreg1 |= ((uint32_t)tmpreg2 << 20);
+
+ /* Write to ADCx SQR1 */
+ ADCx->SQR1 = tmpreg1;
+}
+
+/**
+ * @brief Fills each ADC_InitStruct member with its default value.
+ * @note This function is used to initialize the global features of the ADC (
+ * Resolution and Data Alignment), however, the rest of the configuration
+ * parameters are specific to the regular channels group (scan mode
+ * activation, continuous mode activation, External trigger source and
+ * edge, number of conversion in the regular channels group sequencer).
+ * @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure which will
+ * be initialized.
+ * @retval None
+ */
+void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct)
+{
+ /* Initialize the ADC_Mode member */
+ ADC_InitStruct->ADC_Resolution = ADC_Resolution_12b;
+
+ /* initialize the ADC_ScanConvMode member */
+ ADC_InitStruct->ADC_ScanConvMode = DISABLE;
+
+ /* Initialize the ADC_ContinuousConvMode member */
+ ADC_InitStruct->ADC_ContinuousConvMode = DISABLE;
+
+ /* Initialize the ADC_ExternalTrigConvEdge member */
+ ADC_InitStruct->ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
+
+ /* Initialize the ADC_ExternalTrigConv member */
+ ADC_InitStruct->ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
+
+ /* Initialize the ADC_DataAlign member */
+ ADC_InitStruct->ADC_DataAlign = ADC_DataAlign_Right;
+
+ /* Initialize the ADC_NbrOfConversion member */
+ ADC_InitStruct->ADC_NbrOfConversion = 1;
+}
+
+/**
+ * @brief Initializes the ADCs peripherals according to the specified parameters
+ * in the ADC_CommonInitStruct.
+ * @param ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure
+ * that contains the configuration information for All ADCs peripherals.
+ * @retval None
+ */
+void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct)
+{
+ uint32_t tmpreg1 = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_MODE(ADC_CommonInitStruct->ADC_Mode));
+ assert_param(IS_ADC_PRESCALER(ADC_CommonInitStruct->ADC_Prescaler));
+ assert_param(IS_ADC_DMA_ACCESS_MODE(ADC_CommonInitStruct->ADC_DMAAccessMode));
+ assert_param(IS_ADC_SAMPLING_DELAY(ADC_CommonInitStruct->ADC_TwoSamplingDelay));
+ /*---------------------------- ADC CCR Configuration -----------------*/
+ /* Get the ADC CCR value */
+ tmpreg1 = ADC->CCR;
+
+ /* Clear MULTI, DELAY, DMA and ADCPRE bits */
+ tmpreg1 &= CR_CLEAR_MASK;
+
+ /* Configure ADCx: Multi mode, Delay between two sampling time, ADC prescaler,
+ and DMA access mode for multimode */
+ /* Set MULTI bits according to ADC_Mode value */
+ /* Set ADCPRE bits according to ADC_Prescaler value */
+ /* Set DMA bits according to ADC_DMAAccessMode value */
+ /* Set DELAY bits according to ADC_TwoSamplingDelay value */
+ tmpreg1 |= (uint32_t)(ADC_CommonInitStruct->ADC_Mode |
+ ADC_CommonInitStruct->ADC_Prescaler |
+ ADC_CommonInitStruct->ADC_DMAAccessMode |
+ ADC_CommonInitStruct->ADC_TwoSamplingDelay);
+
+ /* Write to ADC CCR */
+ ADC->CCR = tmpreg1;
+}
+
+/**
+ * @brief Fills each ADC_CommonInitStruct member with its default value.
+ * @param ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure
+ * which will be initialized.
+ * @retval None
+ */
+void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct)
+{
+ /* Initialize the ADC_Mode member */
+ ADC_CommonInitStruct->ADC_Mode = ADC_Mode_Independent;
+
+ /* initialize the ADC_Prescaler member */
+ ADC_CommonInitStruct->ADC_Prescaler = ADC_Prescaler_Div2;
+
+ /* Initialize the ADC_DMAAccessMode member */
+ ADC_CommonInitStruct->ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
+
+ /* Initialize the ADC_TwoSamplingDelay member */
+ ADC_CommonInitStruct->ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
+}
+
+/**
+ * @brief Enables or disables the specified ADC peripheral.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the ADCx peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Set the ADON bit to wake up the ADC from power down mode */
+ ADCx->CR2 |= (uint32_t)ADC_CR2_ADON;
+ }
+ else
+ {
+ /* Disable the selected ADC peripheral */
+ ADCx->CR2 &= (uint32_t)(~ADC_CR2_ADON);
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Group2 Analog Watchdog configuration functions
+ * @brief Analog Watchdog configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Analog Watchdog configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to configure the Analog Watchdog
+ (AWD) feature in the ADC.
+
+ [..] A typical configuration Analog Watchdog is done following these steps :
+ (#) the ADC guarded channel(s) is (are) selected using the
+ ADC_AnalogWatchdogSingleChannelConfig() function.
+ (#) The Analog watchdog lower and higher threshold are configured using the
+ ADC_AnalogWatchdogThresholdsConfig() function.
+ (#) The Analog watchdog is enabled and configured to enable the check, on one
+ or more channels, using the ADC_AnalogWatchdogCmd() function.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the analog watchdog on single/all regular or
+ * injected channels
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_AnalogWatchdog: the ADC analog watchdog configuration.
+ * This parameter can be one of the following values:
+ * @arg ADC_AnalogWatchdog_SingleRegEnable: Analog watchdog on a single regular channel
+ * @arg ADC_AnalogWatchdog_SingleInjecEnable: Analog watchdog on a single injected channel
+ * @arg ADC_AnalogWatchdog_SingleRegOrInjecEnable: Analog watchdog on a single regular or injected channel
+ * @arg ADC_AnalogWatchdog_AllRegEnable: Analog watchdog on all regular channel
+ * @arg ADC_AnalogWatchdog_AllInjecEnable: Analog watchdog on all injected channel
+ * @arg ADC_AnalogWatchdog_AllRegAllInjecEnable: Analog watchdog on all regular and injected channels
+ * @arg ADC_AnalogWatchdog_None: No channel guarded by the analog watchdog
+ * @retval None
+ */
+void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog)
+{
+ uint32_t tmpreg = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_ANALOG_WATCHDOG(ADC_AnalogWatchdog));
+
+ /* Get the old register value */
+ tmpreg = ADCx->CR1;
+
+ /* Clear AWDEN, JAWDEN and AWDSGL bits */
+ tmpreg &= CR1_AWDMode_RESET;
+
+ /* Set the analog watchdog enable mode */
+ tmpreg |= ADC_AnalogWatchdog;
+
+ /* Store the new register value */
+ ADCx->CR1 = tmpreg;
+}
+
+/**
+ * @brief Configures the high and low thresholds of the analog watchdog.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param HighThreshold: the ADC analog watchdog High threshold value.
+ * This parameter must be a 12-bit value.
+ * @param LowThreshold: the ADC analog watchdog Low threshold value.
+ * This parameter must be a 12-bit value.
+ * @retval None
+ */
+void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,
+ uint16_t LowThreshold)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_THRESHOLD(HighThreshold));
+ assert_param(IS_ADC_THRESHOLD(LowThreshold));
+
+ /* Set the ADCx high threshold */
+ ADCx->HTR = HighThreshold;
+
+ /* Set the ADCx low threshold */
+ ADCx->LTR = LowThreshold;
+}
+
+/**
+ * @brief Configures the analog watchdog guarded single channel
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_Channel: the ADC channel to configure for the analog watchdog.
+ * This parameter can be one of the following values:
+ * @arg ADC_Channel_0: ADC Channel0 selected
+ * @arg ADC_Channel_1: ADC Channel1 selected
+ * @arg ADC_Channel_2: ADC Channel2 selected
+ * @arg ADC_Channel_3: ADC Channel3 selected
+ * @arg ADC_Channel_4: ADC Channel4 selected
+ * @arg ADC_Channel_5: ADC Channel5 selected
+ * @arg ADC_Channel_6: ADC Channel6 selected
+ * @arg ADC_Channel_7: ADC Channel7 selected
+ * @arg ADC_Channel_8: ADC Channel8 selected
+ * @arg ADC_Channel_9: ADC Channel9 selected
+ * @arg ADC_Channel_10: ADC Channel10 selected
+ * @arg ADC_Channel_11: ADC Channel11 selected
+ * @arg ADC_Channel_12: ADC Channel12 selected
+ * @arg ADC_Channel_13: ADC Channel13 selected
+ * @arg ADC_Channel_14: ADC Channel14 selected
+ * @arg ADC_Channel_15: ADC Channel15 selected
+ * @arg ADC_Channel_16: ADC Channel16 selected
+ * @arg ADC_Channel_17: ADC Channel17 selected
+ * @arg ADC_Channel_18: ADC Channel18 selected
+ * @retval None
+ */
+void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel)
+{
+ uint32_t tmpreg = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_CHANNEL(ADC_Channel));
+
+ /* Get the old register value */
+ tmpreg = ADCx->CR1;
+
+ /* Clear the Analog watchdog channel select bits */
+ tmpreg &= CR1_AWDCH_RESET;
+
+ /* Set the Analog watchdog channel */
+ tmpreg |= ADC_Channel;
+
+ /* Store the new register value */
+ ADCx->CR1 = tmpreg;
+}
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Group3 Temperature Sensor, Vrefint (Voltage Reference internal)
+ * and VBAT (Voltage BATtery) management functions
+ * @brief Temperature Sensor, Vrefint and VBAT management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Temperature Sensor, Vrefint and VBAT management functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to enable/ disable the internal
+ connections between the ADC and the Temperature Sensor, the Vrefint and
+ the Vbat sources.
+
+ [..] A typical configuration to get the Temperature sensor and Vrefint channels
+ voltages is done following these steps :
+ (#) Enable the internal connection of Temperature sensor and Vrefint sources
+ with the ADC channels using ADC_TempSensorVrefintCmd() function.
+ (#) Select the ADC_Channel_TempSensor and/or ADC_Channel_Vrefint using
+ ADC_RegularChannelConfig() or ADC_InjectedChannelConfig() functions
+ (#) Get the voltage values, using ADC_GetConversionValue() or
+ ADC_GetInjectedConversionValue().
+
+ [..] A typical configuration to get the VBAT channel voltage is done following
+ these steps :
+ (#) Enable the internal connection of VBAT source with the ADC channel using
+ ADC_VBATCmd() function.
+ (#) Select the ADC_Channel_Vbat using ADC_RegularChannelConfig() or
+ ADC_InjectedChannelConfig() functions
+ (#) Get the voltage value, using ADC_GetConversionValue() or
+ ADC_GetInjectedConversionValue().
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Enables or disables the temperature sensor and Vrefint channels.
+ * @param NewState: new state of the temperature sensor and Vrefint channels.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_TempSensorVrefintCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Enable the temperature sensor and Vrefint channel*/
+ ADC->CCR |= (uint32_t)ADC_CCR_TSVREFE;
+ }
+ else
+ {
+ /* Disable the temperature sensor and Vrefint channel*/
+ ADC->CCR &= (uint32_t)(~ADC_CCR_TSVREFE);
+ }
+}
+
+/**
+ * @brief Enables or disables the VBAT (Voltage Battery) channel.
+ *
+ * @note the Battery voltage measured is equal to VBAT/2 on STM32F40xx and
+ * STM32F41xx devices and equal to VBAT/4 on STM32F42xx and STM32F43xx devices
+ *
+ * @param NewState: new state of the VBAT channel.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_VBATCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Enable the VBAT channel*/
+ ADC->CCR |= (uint32_t)ADC_CCR_VBATE;
+ }
+ else
+ {
+ /* Disable the VBAT channel*/
+ ADC->CCR &= (uint32_t)(~ADC_CCR_VBATE);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Group4 Regular Channels Configuration functions
+ * @brief Regular Channels Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Regular Channels Configuration functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to manage the ADC's regular channels,
+ it is composed of 2 sub sections :
+
+ (#) Configuration and management functions for regular channels: This subsection
+ provides functions allowing to configure the ADC regular channels :
+ (++) Configure the rank in the regular group sequencer for each channel
+ (++) Configure the sampling time for each channel
+ (++) select the conversion Trigger for regular channels
+ (++) select the desired EOC event behavior configuration
+ (++) Activate the continuous Mode (*)
+ (++) Activate the Discontinuous Mode
+ -@@- Please Note that the following features for regular channels
+ are configurated using the ADC_Init() function :
+ (+@@) scan mode activation
+ (+@@) continuous mode activation (**)
+ (+@@) External trigger source
+ (+@@) External trigger edge
+ (+@@) number of conversion in the regular channels group sequencer.
+
+ -@@- (*) and (**) are performing the same configuration
+
+ (#) Get the conversion data: This subsection provides an important function in
+ the ADC peripheral since it returns the converted data of the current
+ regular channel. When the Conversion value is read, the EOC Flag is
+ automatically cleared.
+
+ -@- For multi ADC mode, the last ADC1, ADC2 and ADC3 regular conversions
+ results data (in the selected multi mode) can be returned in the same
+ time using ADC_GetMultiModeConversionValue() function.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Configures for the selected ADC regular channel its corresponding
+ * rank in the sequencer and its sample time.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_Channel: the ADC channel to configure.
+ * This parameter can be one of the following values:
+ * @arg ADC_Channel_0: ADC Channel0 selected
+ * @arg ADC_Channel_1: ADC Channel1 selected
+ * @arg ADC_Channel_2: ADC Channel2 selected
+ * @arg ADC_Channel_3: ADC Channel3 selected
+ * @arg ADC_Channel_4: ADC Channel4 selected
+ * @arg ADC_Channel_5: ADC Channel5 selected
+ * @arg ADC_Channel_6: ADC Channel6 selected
+ * @arg ADC_Channel_7: ADC Channel7 selected
+ * @arg ADC_Channel_8: ADC Channel8 selected
+ * @arg ADC_Channel_9: ADC Channel9 selected
+ * @arg ADC_Channel_10: ADC Channel10 selected
+ * @arg ADC_Channel_11: ADC Channel11 selected
+ * @arg ADC_Channel_12: ADC Channel12 selected
+ * @arg ADC_Channel_13: ADC Channel13 selected
+ * @arg ADC_Channel_14: ADC Channel14 selected
+ * @arg ADC_Channel_15: ADC Channel15 selected
+ * @arg ADC_Channel_16: ADC Channel16 selected
+ * @arg ADC_Channel_17: ADC Channel17 selected
+ * @arg ADC_Channel_18: ADC Channel18 selected
+ * @param Rank: The rank in the regular group sequencer.
+ * This parameter must be between 1 to 16.
+ * @param ADC_SampleTime: The sample time value to be set for the selected channel.
+ * This parameter can be one of the following values:
+ * @arg ADC_SampleTime_3Cycles: Sample time equal to 3 cycles
+ * @arg ADC_SampleTime_15Cycles: Sample time equal to 15 cycles
+ * @arg ADC_SampleTime_28Cycles: Sample time equal to 28 cycles
+ * @arg ADC_SampleTime_56Cycles: Sample time equal to 56 cycles
+ * @arg ADC_SampleTime_84Cycles: Sample time equal to 84 cycles
+ * @arg ADC_SampleTime_112Cycles: Sample time equal to 112 cycles
+ * @arg ADC_SampleTime_144Cycles: Sample time equal to 144 cycles
+ * @arg ADC_SampleTime_480Cycles: Sample time equal to 480 cycles
+ * @retval None
+ */
+void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
+{
+ uint32_t tmpreg1 = 0, tmpreg2 = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_CHANNEL(ADC_Channel));
+ assert_param(IS_ADC_REGULAR_RANK(Rank));
+ assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime));
+
+ /* if ADC_Channel_10 ... ADC_Channel_18 is selected */
+ if (ADC_Channel > ADC_Channel_9)
+ {
+ /* Get the old register value */
+ tmpreg1 = ADCx->SMPR1;
+
+ /* Calculate the mask to clear */
+ tmpreg2 = SMPR1_SMP_SET << (3 * (ADC_Channel - 10));
+
+ /* Clear the old sample time */
+ tmpreg1 &= ~tmpreg2;
+
+ /* Calculate the mask to set */
+ tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10));
+
+ /* Set the new sample time */
+ tmpreg1 |= tmpreg2;
+
+ /* Store the new register value */
+ ADCx->SMPR1 = tmpreg1;
+ }
+ else /* ADC_Channel include in ADC_Channel_[0..9] */
+ {
+ /* Get the old register value */
+ tmpreg1 = ADCx->SMPR2;
+
+ /* Calculate the mask to clear */
+ tmpreg2 = SMPR2_SMP_SET << (3 * ADC_Channel);
+
+ /* Clear the old sample time */
+ tmpreg1 &= ~tmpreg2;
+
+ /* Calculate the mask to set */
+ tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel);
+
+ /* Set the new sample time */
+ tmpreg1 |= tmpreg2;
+
+ /* Store the new register value */
+ ADCx->SMPR2 = tmpreg1;
+ }
+ /* For Rank 1 to 6 */
+ if (Rank < 7)
+ {
+ /* Get the old register value */
+ tmpreg1 = ADCx->SQR3;
+
+ /* Calculate the mask to clear */
+ tmpreg2 = SQR3_SQ_SET << (5 * (Rank - 1));
+
+ /* Clear the old SQx bits for the selected rank */
+ tmpreg1 &= ~tmpreg2;
+
+ /* Calculate the mask to set */
+ tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1));
+
+ /* Set the SQx bits for the selected rank */
+ tmpreg1 |= tmpreg2;
+
+ /* Store the new register value */
+ ADCx->SQR3 = tmpreg1;
+ }
+ /* For Rank 7 to 12 */
+ else if (Rank < 13)
+ {
+ /* Get the old register value */
+ tmpreg1 = ADCx->SQR2;
+
+ /* Calculate the mask to clear */
+ tmpreg2 = SQR2_SQ_SET << (5 * (Rank - 7));
+
+ /* Clear the old SQx bits for the selected rank */
+ tmpreg1 &= ~tmpreg2;
+
+ /* Calculate the mask to set */
+ tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7));
+
+ /* Set the SQx bits for the selected rank */
+ tmpreg1 |= tmpreg2;
+
+ /* Store the new register value */
+ ADCx->SQR2 = tmpreg1;
+ }
+ /* For Rank 13 to 16 */
+ else
+ {
+ /* Get the old register value */
+ tmpreg1 = ADCx->SQR1;
+
+ /* Calculate the mask to clear */
+ tmpreg2 = SQR1_SQ_SET << (5 * (Rank - 13));
+
+ /* Clear the old SQx bits for the selected rank */
+ tmpreg1 &= ~tmpreg2;
+
+ /* Calculate the mask to set */
+ tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13));
+
+ /* Set the SQx bits for the selected rank */
+ tmpreg1 |= tmpreg2;
+
+ /* Store the new register value */
+ ADCx->SQR1 = tmpreg1;
+ }
+}
+
+/**
+ * @brief Enables the selected ADC software start conversion of the regular channels.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @retval None
+ */
+void ADC_SoftwareStartConv(ADC_TypeDef* ADCx)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+
+ /* Enable the selected ADC conversion for regular group */
+ ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
+}
+
+/**
+ * @brief Gets the selected ADC Software start regular conversion Status.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @retval The new state of ADC software start conversion (SET or RESET).
+ */
+FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx)
+{
+ FlagStatus bitstatus = RESET;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+
+ /* Check the status of SWSTART bit */
+ if ((ADCx->CR2 & ADC_CR2_SWSTART) != (uint32_t)RESET)
+ {
+ /* SWSTART bit is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* SWSTART bit is reset */
+ bitstatus = RESET;
+ }
+
+ /* Return the SWSTART bit status */
+ return bitstatus;
+}
+
+
+/**
+ * @brief Enables or disables the EOC on each regular channel conversion
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the selected ADC EOC flag rising
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC EOC rising on each regular channel conversion */
+ ADCx->CR2 |= (uint32_t)ADC_CR2_EOCS;
+ }
+ else
+ {
+ /* Disable the selected ADC EOC rising on each regular channel conversion */
+ ADCx->CR2 &= (uint32_t)(~ADC_CR2_EOCS);
+ }
+}
+
+/**
+ * @brief Enables or disables the ADC continuous conversion mode
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the selected ADC continuous conversion mode
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC continuous conversion mode */
+ ADCx->CR2 |= (uint32_t)ADC_CR2_CONT;
+ }
+ else
+ {
+ /* Disable the selected ADC continuous conversion mode */
+ ADCx->CR2 &= (uint32_t)(~ADC_CR2_CONT);
+ }
+}
+
+/**
+ * @brief Configures the discontinuous mode for the selected ADC regular group
+ * channel.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param Number: specifies the discontinuous mode regular channel count value.
+ * This number must be between 1 and 8.
+ * @retval None
+ */
+void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number)
+{
+ uint32_t tmpreg1 = 0;
+ uint32_t tmpreg2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_REGULAR_DISC_NUMBER(Number));
+
+ /* Get the old register value */
+ tmpreg1 = ADCx->CR1;
+
+ /* Clear the old discontinuous mode channel count */
+ tmpreg1 &= CR1_DISCNUM_RESET;
+
+ /* Set the discontinuous mode channel count */
+ tmpreg2 = Number - 1;
+ tmpreg1 |= tmpreg2 << 13;
+
+ /* Store the new register value */
+ ADCx->CR1 = tmpreg1;
+}
+
+/**
+ * @brief Enables or disables the discontinuous mode on regular group channel
+ * for the specified ADC
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the selected ADC discontinuous mode on
+ * regular group channel.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC regular discontinuous mode */
+ ADCx->CR1 |= (uint32_t)ADC_CR1_DISCEN;
+ }
+ else
+ {
+ /* Disable the selected ADC regular discontinuous mode */
+ ADCx->CR1 &= (uint32_t)(~ADC_CR1_DISCEN);
+ }
+}
+
+/**
+ * @brief Returns the last ADCx conversion result data for regular channel.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @retval The Data conversion value.
+ */
+uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+
+ /* Return the selected ADC conversion value */
+ return (uint16_t) ADCx->DR;
+}
+
+/**
+ * @brief Returns the last ADC1, ADC2 and ADC3 regular conversions results
+ * data in the selected multi mode.
+ * @param None
+ * @retval The Data conversion value.
+ * @note In dual mode, the value returned by this function is as following
+ * Data[15:0] : these bits contain the regular data of ADC1.
+ * Data[31:16]: these bits contain the regular data of ADC2.
+ * @note In triple mode, the value returned by this function is as following
+ * Data[15:0] : these bits contain alternatively the regular data of ADC1, ADC3 and ADC2.
+ * Data[31:16]: these bits contain alternatively the regular data of ADC2, ADC1 and ADC3.
+ */
+uint32_t ADC_GetMultiModeConversionValue(void)
+{
+ /* Return the multi mode conversion value */
+ return (*(__IO uint32_t *) CDR_ADDRESS);
+}
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Group5 Regular Channels DMA Configuration functions
+ * @brief Regular Channels DMA Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Regular Channels DMA Configuration functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to configure the DMA for ADC
+ regular channels.
+ Since converted regular channel values are stored into a unique data
+ register, it is useful to use DMA for conversion of more than one regular
+ channel. This avoids the loss of the data already stored in the ADC
+ Data register.
+ When the DMA mode is enabled (using the ADC_DMACmd() function), after each
+ conversion of a regular channel, a DMA request is generated.
+ [..] Depending on the "DMA disable selection for Independent ADC mode"
+ configuration (using the ADC_DMARequestAfterLastTransferCmd() function),
+ at the end of the last DMA transfer, two possibilities are allowed:
+ (+) No new DMA request is issued to the DMA controller (feature DISABLED)
+ (+) Requests can continue to be generated (feature ENABLED).
+ [..] Depending on the "DMA disable selection for multi ADC mode" configuration
+ (using the void ADC_MultiModeDMARequestAfterLastTransferCmd() function),
+ at the end of the last DMA transfer, two possibilities are allowed:
+ (+) No new DMA request is issued to the DMA controller (feature DISABLED)
+ (+) Requests can continue to be generated (feature ENABLED).
+
+@endverbatim
+ * @{
+ */
+
+ /**
+ * @brief Enables or disables the specified ADC DMA request.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the selected ADC DMA transfer.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC DMA request */
+ ADCx->CR2 |= (uint32_t)ADC_CR2_DMA;
+ }
+ else
+ {
+ /* Disable the selected ADC DMA request */
+ ADCx->CR2 &= (uint32_t)(~ADC_CR2_DMA);
+ }
+}
+
+/**
+ * @brief Enables or disables the ADC DMA request after last transfer (Single-ADC mode)
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the selected ADC DMA request after last transfer.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC DMA request after last transfer */
+ ADCx->CR2 |= (uint32_t)ADC_CR2_DDS;
+ }
+ else
+ {
+ /* Disable the selected ADC DMA request after last transfer */
+ ADCx->CR2 &= (uint32_t)(~ADC_CR2_DDS);
+ }
+}
+
+/**
+ * @brief Enables or disables the ADC DMA request after last transfer in multi ADC mode
+ * @param NewState: new state of the selected ADC DMA request after last transfer.
+ * This parameter can be: ENABLE or DISABLE.
+ * @note if Enabled, DMA requests are issued as long as data are converted and
+ * DMA mode for multi ADC mode (selected using ADC_CommonInit() function
+ * by ADC_CommonInitStruct.ADC_DMAAccessMode structure member) is
+ * ADC_DMAAccessMode_1, ADC_DMAAccessMode_2 or ADC_DMAAccessMode_3.
+ * @retval None
+ */
+void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC DMA request after last transfer */
+ ADC->CCR |= (uint32_t)ADC_CCR_DDS;
+ }
+ else
+ {
+ /* Disable the selected ADC DMA request after last transfer */
+ ADC->CCR &= (uint32_t)(~ADC_CCR_DDS);
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Group6 Injected channels Configuration functions
+ * @brief Injected channels Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Injected channels Configuration functions #####
+ ===============================================================================
+
+ [..] This section provide functions allowing to configure the ADC Injected channels,
+ it is composed of 2 sub sections :
+
+ (#) Configuration functions for Injected channels: This subsection provides
+ functions allowing to configure the ADC injected channels :
+ (++) Configure the rank in the injected group sequencer for each channel
+ (++) Configure the sampling time for each channel
+ (++) Activate the Auto injected Mode
+ (++) Activate the Discontinuous Mode
+ (++) scan mode activation
+ (++) External/software trigger source
+ (++) External trigger edge
+ (++) injected channels sequencer.
+
+ (#) Get the Specified Injected channel conversion data: This subsection
+ provides an important function in the ADC peripheral since it returns the
+ converted data of the specific injected channel.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Configures for the selected ADC injected channel its corresponding
+ * rank in the sequencer and its sample time.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_Channel: the ADC channel to configure.
+ * This parameter can be one of the following values:
+ * @arg ADC_Channel_0: ADC Channel0 selected
+ * @arg ADC_Channel_1: ADC Channel1 selected
+ * @arg ADC_Channel_2: ADC Channel2 selected
+ * @arg ADC_Channel_3: ADC Channel3 selected
+ * @arg ADC_Channel_4: ADC Channel4 selected
+ * @arg ADC_Channel_5: ADC Channel5 selected
+ * @arg ADC_Channel_6: ADC Channel6 selected
+ * @arg ADC_Channel_7: ADC Channel7 selected
+ * @arg ADC_Channel_8: ADC Channel8 selected
+ * @arg ADC_Channel_9: ADC Channel9 selected
+ * @arg ADC_Channel_10: ADC Channel10 selected
+ * @arg ADC_Channel_11: ADC Channel11 selected
+ * @arg ADC_Channel_12: ADC Channel12 selected
+ * @arg ADC_Channel_13: ADC Channel13 selected
+ * @arg ADC_Channel_14: ADC Channel14 selected
+ * @arg ADC_Channel_15: ADC Channel15 selected
+ * @arg ADC_Channel_16: ADC Channel16 selected
+ * @arg ADC_Channel_17: ADC Channel17 selected
+ * @arg ADC_Channel_18: ADC Channel18 selected
+ * @param Rank: The rank in the injected group sequencer.
+ * This parameter must be between 1 to 4.
+ * @param ADC_SampleTime: The sample time value to be set for the selected channel.
+ * This parameter can be one of the following values:
+ * @arg ADC_SampleTime_3Cycles: Sample time equal to 3 cycles
+ * @arg ADC_SampleTime_15Cycles: Sample time equal to 15 cycles
+ * @arg ADC_SampleTime_28Cycles: Sample time equal to 28 cycles
+ * @arg ADC_SampleTime_56Cycles: Sample time equal to 56 cycles
+ * @arg ADC_SampleTime_84Cycles: Sample time equal to 84 cycles
+ * @arg ADC_SampleTime_112Cycles: Sample time equal to 112 cycles
+ * @arg ADC_SampleTime_144Cycles: Sample time equal to 144 cycles
+ * @arg ADC_SampleTime_480Cycles: Sample time equal to 480 cycles
+ * @retval None
+ */
+void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
+{
+ uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_CHANNEL(ADC_Channel));
+ assert_param(IS_ADC_INJECTED_RANK(Rank));
+ assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime));
+ /* if ADC_Channel_10 ... ADC_Channel_18 is selected */
+ if (ADC_Channel > ADC_Channel_9)
+ {
+ /* Get the old register value */
+ tmpreg1 = ADCx->SMPR1;
+ /* Calculate the mask to clear */
+ tmpreg2 = SMPR1_SMP_SET << (3*(ADC_Channel - 10));
+ /* Clear the old sample time */
+ tmpreg1 &= ~tmpreg2;
+ /* Calculate the mask to set */
+ tmpreg2 = (uint32_t)ADC_SampleTime << (3*(ADC_Channel - 10));
+ /* Set the new sample time */
+ tmpreg1 |= tmpreg2;
+ /* Store the new register value */
+ ADCx->SMPR1 = tmpreg1;
+ }
+ else /* ADC_Channel include in ADC_Channel_[0..9] */
+ {
+ /* Get the old register value */
+ tmpreg1 = ADCx->SMPR2;
+ /* Calculate the mask to clear */
+ tmpreg2 = SMPR2_SMP_SET << (3 * ADC_Channel);
+ /* Clear the old sample time */
+ tmpreg1 &= ~tmpreg2;
+ /* Calculate the mask to set */
+ tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel);
+ /* Set the new sample time */
+ tmpreg1 |= tmpreg2;
+ /* Store the new register value */
+ ADCx->SMPR2 = tmpreg1;
+ }
+ /* Rank configuration */
+ /* Get the old register value */
+ tmpreg1 = ADCx->JSQR;
+ /* Get JL value: Number = JL+1 */
+ tmpreg3 = (tmpreg1 & JSQR_JL_SET)>> 20;
+ /* Calculate the mask to clear: ((Rank-1)+(4-JL-1)) */
+ tmpreg2 = JSQR_JSQ_SET << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1)));
+ /* Clear the old JSQx bits for the selected rank */
+ tmpreg1 &= ~tmpreg2;
+ /* Calculate the mask to set: ((Rank-1)+(4-JL-1)) */
+ tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1)));
+ /* Set the JSQx bits for the selected rank */
+ tmpreg1 |= tmpreg2;
+ /* Store the new register value */
+ ADCx->JSQR = tmpreg1;
+}
+
+/**
+ * @brief Configures the sequencer length for injected channels
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param Length: The sequencer length.
+ * This parameter must be a number between 1 to 4.
+ * @retval None
+ */
+void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length)
+{
+ uint32_t tmpreg1 = 0;
+ uint32_t tmpreg2 = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_INJECTED_LENGTH(Length));
+
+ /* Get the old register value */
+ tmpreg1 = ADCx->JSQR;
+
+ /* Clear the old injected sequence length JL bits */
+ tmpreg1 &= JSQR_JL_RESET;
+
+ /* Set the injected sequence length JL bits */
+ tmpreg2 = Length - 1;
+ tmpreg1 |= tmpreg2 << 20;
+
+ /* Store the new register value */
+ ADCx->JSQR = tmpreg1;
+}
+
+/**
+ * @brief Set the injected channels conversion value offset
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_InjectedChannel: the ADC injected channel to set its offset.
+ * This parameter can be one of the following values:
+ * @arg ADC_InjectedChannel_1: Injected Channel1 selected
+ * @arg ADC_InjectedChannel_2: Injected Channel2 selected
+ * @arg ADC_InjectedChannel_3: Injected Channel3 selected
+ * @arg ADC_InjectedChannel_4: Injected Channel4 selected
+ * @param Offset: the offset value for the selected ADC injected channel
+ * This parameter must be a 12bit value.
+ * @retval None
+ */
+void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset)
+{
+ __IO uint32_t tmp = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel));
+ assert_param(IS_ADC_OFFSET(Offset));
+
+ tmp = (uint32_t)ADCx;
+ tmp += ADC_InjectedChannel;
+
+ /* Set the selected injected channel data offset */
+ *(__IO uint32_t *) tmp = (uint32_t)Offset;
+}
+
+ /**
+ * @brief Configures the ADCx external trigger for injected channels conversion.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_ExternalTrigInjecConv: specifies the ADC trigger to start injected conversion.
+ * This parameter can be one of the following values:
+ * @arg ADC_ExternalTrigInjecConv_T1_CC4: Timer1 capture compare4 selected
+ * @arg ADC_ExternalTrigInjecConv_T1_TRGO: Timer1 TRGO event selected
+ * @arg ADC_ExternalTrigInjecConv_T2_CC1: Timer2 capture compare1 selected
+ * @arg ADC_ExternalTrigInjecConv_T2_TRGO: Timer2 TRGO event selected
+ * @arg ADC_ExternalTrigInjecConv_T3_CC2: Timer3 capture compare2 selected
+ * @arg ADC_ExternalTrigInjecConv_T3_CC4: Timer3 capture compare4 selected
+ * @arg ADC_ExternalTrigInjecConv_T4_CC1: Timer4 capture compare1 selected
+ * @arg ADC_ExternalTrigInjecConv_T4_CC2: Timer4 capture compare2 selected
+ * @arg ADC_ExternalTrigInjecConv_T4_CC3: Timer4 capture compare3 selected
+ * @arg ADC_ExternalTrigInjecConv_T4_TRGO: Timer4 TRGO event selected
+ * @arg ADC_ExternalTrigInjecConv_T5_CC4: Timer5 capture compare4 selected
+ * @arg ADC_ExternalTrigInjecConv_T5_TRGO: Timer5 TRGO event selected
+ * @arg ADC_ExternalTrigInjecConv_T8_CC2: Timer8 capture compare2 selected
+ * @arg ADC_ExternalTrigInjecConv_T8_CC3: Timer8 capture compare3 selected
+ * @arg ADC_ExternalTrigInjecConv_T8_CC4: Timer8 capture compare4 selected
+ * @arg ADC_ExternalTrigInjecConv_Ext_IT15: External interrupt line 15 event selected
+ * @retval None
+ */
+void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv)
+{
+ uint32_t tmpreg = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_EXT_INJEC_TRIG(ADC_ExternalTrigInjecConv));
+
+ /* Get the old register value */
+ tmpreg = ADCx->CR2;
+
+ /* Clear the old external event selection for injected group */
+ tmpreg &= CR2_JEXTSEL_RESET;
+
+ /* Set the external event selection for injected group */
+ tmpreg |= ADC_ExternalTrigInjecConv;
+
+ /* Store the new register value */
+ ADCx->CR2 = tmpreg;
+}
+
+/**
+ * @brief Configures the ADCx external trigger edge for injected channels conversion.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_ExternalTrigInjecConvEdge: specifies the ADC external trigger edge
+ * to start injected conversion.
+ * This parameter can be one of the following values:
+ * @arg ADC_ExternalTrigInjecConvEdge_None: external trigger disabled for
+ * injected conversion
+ * @arg ADC_ExternalTrigInjecConvEdge_Rising: detection on rising edge
+ * @arg ADC_ExternalTrigInjecConvEdge_Falling: detection on falling edge
+ * @arg ADC_ExternalTrigInjecConvEdge_RisingFalling: detection on both rising
+ * and falling edge
+ * @retval None
+ */
+void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge)
+{
+ uint32_t tmpreg = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_EXT_INJEC_TRIG_EDGE(ADC_ExternalTrigInjecConvEdge));
+ /* Get the old register value */
+ tmpreg = ADCx->CR2;
+ /* Clear the old external trigger edge for injected group */
+ tmpreg &= CR2_JEXTEN_RESET;
+ /* Set the new external trigger edge for injected group */
+ tmpreg |= ADC_ExternalTrigInjecConvEdge;
+ /* Store the new register value */
+ ADCx->CR2 = tmpreg;
+}
+
+/**
+ * @brief Enables the selected ADC software start conversion of the injected channels.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @retval None
+ */
+void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ /* Enable the selected ADC conversion for injected group */
+ ADCx->CR2 |= (uint32_t)ADC_CR2_JSWSTART;
+}
+
+/**
+ * @brief Gets the selected ADC Software start injected conversion Status.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @retval The new state of ADC software start injected conversion (SET or RESET).
+ */
+FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx)
+{
+ FlagStatus bitstatus = RESET;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+
+ /* Check the status of JSWSTART bit */
+ if ((ADCx->CR2 & ADC_CR2_JSWSTART) != (uint32_t)RESET)
+ {
+ /* JSWSTART bit is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* JSWSTART bit is reset */
+ bitstatus = RESET;
+ }
+ /* Return the JSWSTART bit status */
+ return bitstatus;
+}
+
+/**
+ * @brief Enables or disables the selected ADC automatic injected group
+ * conversion after regular one.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the selected ADC auto injected conversion
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC automatic injected group conversion */
+ ADCx->CR1 |= (uint32_t)ADC_CR1_JAUTO;
+ }
+ else
+ {
+ /* Disable the selected ADC automatic injected group conversion */
+ ADCx->CR1 &= (uint32_t)(~ADC_CR1_JAUTO);
+ }
+}
+
+/**
+ * @brief Enables or disables the discontinuous mode for injected group
+ * channel for the specified ADC
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param NewState: new state of the selected ADC discontinuous mode on injected
+ * group channel.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC injected discontinuous mode */
+ ADCx->CR1 |= (uint32_t)ADC_CR1_JDISCEN;
+ }
+ else
+ {
+ /* Disable the selected ADC injected discontinuous mode */
+ ADCx->CR1 &= (uint32_t)(~ADC_CR1_JDISCEN);
+ }
+}
+
+/**
+ * @brief Returns the ADC injected channel conversion result
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_InjectedChannel: the converted ADC injected channel.
+ * This parameter can be one of the following values:
+ * @arg ADC_InjectedChannel_1: Injected Channel1 selected
+ * @arg ADC_InjectedChannel_2: Injected Channel2 selected
+ * @arg ADC_InjectedChannel_3: Injected Channel3 selected
+ * @arg ADC_InjectedChannel_4: Injected Channel4 selected
+ * @retval The Data conversion value.
+ */
+uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel)
+{
+ __IO uint32_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel));
+
+ tmp = (uint32_t)ADCx;
+ tmp += ADC_InjectedChannel + JDR_OFFSET;
+
+ /* Returns the selected injected channel conversion data value */
+ return (uint16_t) (*(__IO uint32_t*) tmp);
+}
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Group7 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Interrupts and flags management functions #####
+ ===============================================================================
+
+ [..] This section provides functions allowing to configure the ADC Interrupts
+ and to get the status and clear flags and Interrupts pending bits.
+
+ [..] Each ADC provides 4 Interrupts sources and 6 Flags which can be divided
+ into 3 groups:
+
+ *** Flags and Interrupts for ADC regular channels ***
+ =====================================================
+ [..]
+ (+) Flags :
+ (##) ADC_FLAG_OVR : Overrun detection when regular converted data are lost
+
+ (##) ADC_FLAG_EOC : Regular channel end of conversion ==> to indicate
+ (depending on EOCS bit, managed by ADC_EOCOnEachRegularChannelCmd() )
+ the end of:
+ (+++) a regular CHANNEL conversion
+ (+++) sequence of regular GROUP conversions .
+
+ (##) ADC_FLAG_STRT: Regular channel start ==> to indicate when regular
+ CHANNEL conversion starts.
+ [..]
+ (+) Interrupts :
+ (##) ADC_IT_OVR : specifies the interrupt source for Overrun detection
+ event.
+ (##) ADC_IT_EOC : specifies the interrupt source for Regular channel end
+ of conversion event.
+
+
+ *** Flags and Interrupts for ADC Injected channels ***
+ ======================================================
+ [..]
+ (+) Flags :
+ (##) ADC_FLAG_JEOC : Injected channel end of conversion ==> to indicate
+ at the end of injected GROUP conversion
+
+ (##) ADC_FLAG_JSTRT: Injected channel start ==> to indicate hardware when
+ injected GROUP conversion starts.
+ [..]
+ (+) Interrupts :
+ (##) ADC_IT_JEOC : specifies the interrupt source for Injected channel
+ end of conversion event.
+
+ *** General Flags and Interrupts for the ADC ***
+ ================================================
+ [..]
+ (+)Flags :
+ (##) ADC_FLAG_AWD: Analog watchdog ==> to indicate if the converted voltage
+ crosses the programmed thresholds values.
+ [..]
+ (+) Interrupts :
+ (##) ADC_IT_AWD : specifies the interrupt source for Analog watchdog event.
+
+
+ [..] The user should identify which mode will be used in his application to
+ manage the ADC controller events: Polling mode or Interrupt mode.
+
+ [..] In the Polling Mode it is advised to use the following functions:
+ (+) ADC_GetFlagStatus() : to check if flags events occur.
+ (+) ADC_ClearFlag() : to clear the flags events.
+
+ [..] In the Interrupt Mode it is advised to use the following functions:
+ (+) ADC_ITConfig() : to enable or disable the interrupt source.
+ (+) ADC_GetITStatus() : to check if Interrupt occurs.
+ (+) ADC_ClearITPendingBit() : to clear the Interrupt pending Bit
+ (corresponding Flag).
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Enables or disables the specified ADC interrupts.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_IT: specifies the ADC interrupt sources to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg ADC_IT_EOC: End of conversion interrupt mask
+ * @arg ADC_IT_AWD: Analog watchdog interrupt mask
+ * @arg ADC_IT_JEOC: End of injected conversion interrupt mask
+ * @arg ADC_IT_OVR: Overrun interrupt enable
+ * @param NewState: new state of the specified ADC interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState)
+{
+ uint32_t itmask = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_ADC_IT(ADC_IT));
+
+ /* Get the ADC IT index */
+ itmask = (uint8_t)ADC_IT;
+ itmask = (uint32_t)0x01 << itmask;
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC interrupts */
+ ADCx->CR1 |= itmask;
+ }
+ else
+ {
+ /* Disable the selected ADC interrupts */
+ ADCx->CR1 &= (~(uint32_t)itmask);
+ }
+}
+
+/**
+ * @brief Checks whether the specified ADC flag is set or not.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_FLAG: specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg ADC_FLAG_AWD: Analog watchdog flag
+ * @arg ADC_FLAG_EOC: End of conversion flag
+ * @arg ADC_FLAG_JEOC: End of injected group conversion flag
+ * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag
+ * @arg ADC_FLAG_STRT: Start of regular group conversion flag
+ * @arg ADC_FLAG_OVR: Overrun flag
+ * @retval The new state of ADC_FLAG (SET or RESET).
+ */
+FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
+{
+ FlagStatus bitstatus = RESET;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_GET_FLAG(ADC_FLAG));
+
+ /* Check the status of the specified ADC flag */
+ if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET)
+ {
+ /* ADC_FLAG is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* ADC_FLAG is reset */
+ bitstatus = RESET;
+ }
+ /* Return the ADC_FLAG status */
+ return bitstatus;
+}
+
+/**
+ * @brief Clears the ADCx's pending flags.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_FLAG: specifies the flag to clear.
+ * This parameter can be any combination of the following values:
+ * @arg ADC_FLAG_AWD: Analog watchdog flag
+ * @arg ADC_FLAG_EOC: End of conversion flag
+ * @arg ADC_FLAG_JEOC: End of injected group conversion flag
+ * @arg ADC_FLAG_JSTRT: Start of injected group conversion flag
+ * @arg ADC_FLAG_STRT: Start of regular group conversion flag
+ * @arg ADC_FLAG_OVR: Overrun flag
+ * @retval None
+ */
+void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG));
+
+ /* Clear the selected ADC flags */
+ ADCx->SR = ~(uint32_t)ADC_FLAG;
+}
+
+/**
+ * @brief Checks whether the specified ADC interrupt has occurred or not.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_IT: specifies the ADC interrupt source to check.
+ * This parameter can be one of the following values:
+ * @arg ADC_IT_EOC: End of conversion interrupt mask
+ * @arg ADC_IT_AWD: Analog watchdog interrupt mask
+ * @arg ADC_IT_JEOC: End of injected conversion interrupt mask
+ * @arg ADC_IT_OVR: Overrun interrupt mask
+ * @retval The new state of ADC_IT (SET or RESET).
+ */
+ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT)
+{
+ ITStatus bitstatus = RESET;
+ uint32_t itmask = 0, enablestatus = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_IT(ADC_IT));
+
+ /* Get the ADC IT index */
+ itmask = ADC_IT >> 8;
+
+ /* Get the ADC_IT enable bit status */
+ enablestatus = (ADCx->CR1 & ((uint32_t)0x01 << (uint8_t)ADC_IT)) ;
+
+ /* Check the status of the specified ADC interrupt */
+ if (((ADCx->SR & itmask) != (uint32_t)RESET) && enablestatus)
+ {
+ /* ADC_IT is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* ADC_IT is reset */
+ bitstatus = RESET;
+ }
+ /* Return the ADC_IT status */
+ return bitstatus;
+}
+
+/**
+ * @brief Clears the ADCx's interrupt pending bits.
+ * @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
+ * @param ADC_IT: specifies the ADC interrupt pending bit to clear.
+ * This parameter can be one of the following values:
+ * @arg ADC_IT_EOC: End of conversion interrupt mask
+ * @arg ADC_IT_AWD: Analog watchdog interrupt mask
+ * @arg ADC_IT_JEOC: End of injected conversion interrupt mask
+ * @arg ADC_IT_OVR: Overrun interrupt mask
+ * @retval None
+ */
+void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT)
+{
+ uint8_t itmask = 0;
+ /* Check the parameters */
+ assert_param(IS_ADC_ALL_PERIPH(ADCx));
+ assert_param(IS_ADC_IT(ADC_IT));
+ /* Get the ADC IT index */
+ itmask = (uint8_t)(ADC_IT >> 8);
+ /* Clear the selected ADC interrupt pending bits */
+ ADCx->SR = ~(uint32_t)itmask;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm/lib/stm32f4xx_adc.h b/stm/lib/stm32f4xx_adc.h new file mode 100644 index 0000000000..9f5fe7acce --- /dev/null +++ b/stm/lib/stm32f4xx_adc.h @@ -0,0 +1,656 @@ +/**
+ ******************************************************************************
+ * @file stm32f4xx_adc.h
+ * @author MCD Application Team
+ * @version V1.3.0
+ * @date 08-November-2013
+ * @brief This file contains all the functions prototypes for the ADC firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_ADC_H
+#define __STM32F4xx_ADC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx.h"
+
+/** @addtogroup STM32F4xx_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup ADC
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/**
+ * @brief ADC Init structure definition
+ */
+typedef struct
+{
+ uint32_t ADC_Resolution; /*!< Configures the ADC resolution dual mode.
+ This parameter can be a value of @ref ADC_resolution */
+ FunctionalState ADC_ScanConvMode; /*!< Specifies whether the conversion
+ is performed in Scan (multichannels)
+ or Single (one channel) mode.
+ This parameter can be set to ENABLE or DISABLE */
+ FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion
+ is performed in Continuous or Single mode.
+ This parameter can be set to ENABLE or DISABLE. */
+ uint32_t ADC_ExternalTrigConvEdge; /*!< Select the external trigger edge and
+ enable the trigger of a regular group.
+ This parameter can be a value of
+ @ref ADC_external_trigger_edge_for_regular_channels_conversion */
+ uint32_t ADC_ExternalTrigConv; /*!< Select the external event used to trigger
+ the start of conversion of a regular group.
+ This parameter can be a value of
+ @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */
+ uint32_t ADC_DataAlign; /*!< Specifies whether the ADC data alignment
+ is left or right. This parameter can be
+ a value of @ref ADC_data_align */
+ uint8_t ADC_NbrOfConversion; /*!< Specifies the number of ADC conversions
+ that will be done using the sequencer for
+ regular channel group.
+ This parameter must range from 1 to 16. */
+}ADC_InitTypeDef;
+
+/**
+ * @brief ADC Common Init structure definition
+ */
+typedef struct
+{
+ uint32_t ADC_Mode; /*!< Configures the ADC to operate in
+ independent or multi mode.
+ This parameter can be a value of @ref ADC_Common_mode */
+ uint32_t ADC_Prescaler; /*!< Select the frequency of the clock
+ to the ADC. The clock is common for all the ADCs.
+ This parameter can be a value of @ref ADC_Prescaler */
+ uint32_t ADC_DMAAccessMode; /*!< Configures the Direct memory access
+ mode for multi ADC mode.
+ This parameter can be a value of
+ @ref ADC_Direct_memory_access_mode_for_multi_mode */
+ uint32_t ADC_TwoSamplingDelay; /*!< Configures the Delay between 2 sampling phases.
+ This parameter can be a value of
+ @ref ADC_delay_between_2_sampling_phases */
+
+}ADC_CommonInitTypeDef;
+
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup ADC_Exported_Constants
+ * @{
+ */
+#define IS_ADC_ALL_PERIPH(PERIPH) (((PERIPH) == ADC1) || \
+ ((PERIPH) == ADC2) || \
+ ((PERIPH) == ADC3))
+
+/** @defgroup ADC_Common_mode
+ * @{
+ */
+#define ADC_Mode_Independent ((uint32_t)0x00000000)
+#define ADC_DualMode_RegSimult_InjecSimult ((uint32_t)0x00000001)
+#define ADC_DualMode_RegSimult_AlterTrig ((uint32_t)0x00000002)
+#define ADC_DualMode_InjecSimult ((uint32_t)0x00000005)
+#define ADC_DualMode_RegSimult ((uint32_t)0x00000006)
+#define ADC_DualMode_Interl ((uint32_t)0x00000007)
+#define ADC_DualMode_AlterTrig ((uint32_t)0x00000009)
+#define ADC_TripleMode_RegSimult_InjecSimult ((uint32_t)0x00000011)
+#define ADC_TripleMode_RegSimult_AlterTrig ((uint32_t)0x00000012)
+#define ADC_TripleMode_InjecSimult ((uint32_t)0x00000015)
+#define ADC_TripleMode_RegSimult ((uint32_t)0x00000016)
+#define ADC_TripleMode_Interl ((uint32_t)0x00000017)
+#define ADC_TripleMode_AlterTrig ((uint32_t)0x00000019)
+#define IS_ADC_MODE(MODE) (((MODE) == ADC_Mode_Independent) || \
+ ((MODE) == ADC_DualMode_RegSimult_InjecSimult) || \
+ ((MODE) == ADC_DualMode_RegSimult_AlterTrig) || \
+ ((MODE) == ADC_DualMode_InjecSimult) || \
+ ((MODE) == ADC_DualMode_RegSimult) || \
+ ((MODE) == ADC_DualMode_Interl) || \
+ ((MODE) == ADC_DualMode_AlterTrig) || \
+ ((MODE) == ADC_TripleMode_RegSimult_InjecSimult) || \
+ ((MODE) == ADC_TripleMode_RegSimult_AlterTrig) || \
+ ((MODE) == ADC_TripleMode_InjecSimult) || \
+ ((MODE) == ADC_TripleMode_RegSimult) || \
+ ((MODE) == ADC_TripleMode_Interl) || \
+ ((MODE) == ADC_TripleMode_AlterTrig))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_Prescaler
+ * @{
+ */
+#define ADC_Prescaler_Div2 ((uint32_t)0x00000000)
+#define ADC_Prescaler_Div4 ((uint32_t)0x00010000)
+#define ADC_Prescaler_Div6 ((uint32_t)0x00020000)
+#define ADC_Prescaler_Div8 ((uint32_t)0x00030000)
+#define IS_ADC_PRESCALER(PRESCALER) (((PRESCALER) == ADC_Prescaler_Div2) || \
+ ((PRESCALER) == ADC_Prescaler_Div4) || \
+ ((PRESCALER) == ADC_Prescaler_Div6) || \
+ ((PRESCALER) == ADC_Prescaler_Div8))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_Direct_memory_access_mode_for_multi_mode
+ * @{
+ */
+#define ADC_DMAAccessMode_Disabled ((uint32_t)0x00000000) /* DMA mode disabled */
+#define ADC_DMAAccessMode_1 ((uint32_t)0x00004000) /* DMA mode 1 enabled (2 / 3 half-words one by one - 1 then 2 then 3)*/
+#define ADC_DMAAccessMode_2 ((uint32_t)0x00008000) /* DMA mode 2 enabled (2 / 3 half-words by pairs - 2&1 then 1&3 then 3&2)*/
+#define ADC_DMAAccessMode_3 ((uint32_t)0x0000C000) /* DMA mode 3 enabled (2 / 3 bytes by pairs - 2&1 then 1&3 then 3&2) */
+#define IS_ADC_DMA_ACCESS_MODE(MODE) (((MODE) == ADC_DMAAccessMode_Disabled) || \
+ ((MODE) == ADC_DMAAccessMode_1) || \
+ ((MODE) == ADC_DMAAccessMode_2) || \
+ ((MODE) == ADC_DMAAccessMode_3))
+
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_delay_between_2_sampling_phases
+ * @{
+ */
+#define ADC_TwoSamplingDelay_5Cycles ((uint32_t)0x00000000)
+#define ADC_TwoSamplingDelay_6Cycles ((uint32_t)0x00000100)
+#define ADC_TwoSamplingDelay_7Cycles ((uint32_t)0x00000200)
+#define ADC_TwoSamplingDelay_8Cycles ((uint32_t)0x00000300)
+#define ADC_TwoSamplingDelay_9Cycles ((uint32_t)0x00000400)
+#define ADC_TwoSamplingDelay_10Cycles ((uint32_t)0x00000500)
+#define ADC_TwoSamplingDelay_11Cycles ((uint32_t)0x00000600)
+#define ADC_TwoSamplingDelay_12Cycles ((uint32_t)0x00000700)
+#define ADC_TwoSamplingDelay_13Cycles ((uint32_t)0x00000800)
+#define ADC_TwoSamplingDelay_14Cycles ((uint32_t)0x00000900)
+#define ADC_TwoSamplingDelay_15Cycles ((uint32_t)0x00000A00)
+#define ADC_TwoSamplingDelay_16Cycles ((uint32_t)0x00000B00)
+#define ADC_TwoSamplingDelay_17Cycles ((uint32_t)0x00000C00)
+#define ADC_TwoSamplingDelay_18Cycles ((uint32_t)0x00000D00)
+#define ADC_TwoSamplingDelay_19Cycles ((uint32_t)0x00000E00)
+#define ADC_TwoSamplingDelay_20Cycles ((uint32_t)0x00000F00)
+#define IS_ADC_SAMPLING_DELAY(DELAY) (((DELAY) == ADC_TwoSamplingDelay_5Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_6Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_7Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_8Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_9Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_10Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_11Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_12Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_13Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_14Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_15Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_16Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_17Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_18Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_19Cycles) || \
+ ((DELAY) == ADC_TwoSamplingDelay_20Cycles))
+
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_resolution
+ * @{
+ */
+#define ADC_Resolution_12b ((uint32_t)0x00000000)
+#define ADC_Resolution_10b ((uint32_t)0x01000000)
+#define ADC_Resolution_8b ((uint32_t)0x02000000)
+#define ADC_Resolution_6b ((uint32_t)0x03000000)
+#define IS_ADC_RESOLUTION(RESOLUTION) (((RESOLUTION) == ADC_Resolution_12b) || \
+ ((RESOLUTION) == ADC_Resolution_10b) || \
+ ((RESOLUTION) == ADC_Resolution_8b) || \
+ ((RESOLUTION) == ADC_Resolution_6b))
+
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_external_trigger_edge_for_regular_channels_conversion
+ * @{
+ */
+#define ADC_ExternalTrigConvEdge_None ((uint32_t)0x00000000)
+#define ADC_ExternalTrigConvEdge_Rising ((uint32_t)0x10000000)
+#define ADC_ExternalTrigConvEdge_Falling ((uint32_t)0x20000000)
+#define ADC_ExternalTrigConvEdge_RisingFalling ((uint32_t)0x30000000)
+#define IS_ADC_EXT_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigConvEdge_None) || \
+ ((EDGE) == ADC_ExternalTrigConvEdge_Rising) || \
+ ((EDGE) == ADC_ExternalTrigConvEdge_Falling) || \
+ ((EDGE) == ADC_ExternalTrigConvEdge_RisingFalling))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion
+ * @{
+ */
+#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000)
+#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x01000000)
+#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x02000000)
+#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x03000000)
+#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x04000000)
+#define ADC_ExternalTrigConv_T2_CC4 ((uint32_t)0x05000000)
+#define ADC_ExternalTrigConv_T2_TRGO ((uint32_t)0x06000000)
+#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x07000000)
+#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x08000000)
+#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x09000000)
+#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x0A000000)
+#define ADC_ExternalTrigConv_T5_CC2 ((uint32_t)0x0B000000)
+#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x0C000000)
+#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x0D000000)
+#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x0E000000)
+#define ADC_ExternalTrigConv_Ext_IT11 ((uint32_t)0x0F000000)
+#define IS_ADC_EXT_TRIG(REGTRIG) (((REGTRIG) == ADC_ExternalTrigConv_T1_CC1) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T1_CC2) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T1_CC3) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T2_CC2) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T2_CC3) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T2_CC4) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T2_TRGO) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T3_CC1) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T3_TRGO) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T4_CC4) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T5_CC1) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T5_CC2) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T5_CC3) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T8_CC1) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_T8_TRGO) || \
+ ((REGTRIG) == ADC_ExternalTrigConv_Ext_IT11))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_data_align
+ * @{
+ */
+#define ADC_DataAlign_Right ((uint32_t)0x00000000)
+#define ADC_DataAlign_Left ((uint32_t)0x00000800)
+#define IS_ADC_DATA_ALIGN(ALIGN) (((ALIGN) == ADC_DataAlign_Right) || \
+ ((ALIGN) == ADC_DataAlign_Left))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_channels
+ * @{
+ */
+#define ADC_Channel_0 ((uint8_t)0x00)
+#define ADC_Channel_1 ((uint8_t)0x01)
+#define ADC_Channel_2 ((uint8_t)0x02)
+#define ADC_Channel_3 ((uint8_t)0x03)
+#define ADC_Channel_4 ((uint8_t)0x04)
+#define ADC_Channel_5 ((uint8_t)0x05)
+#define ADC_Channel_6 ((uint8_t)0x06)
+#define ADC_Channel_7 ((uint8_t)0x07)
+#define ADC_Channel_8 ((uint8_t)0x08)
+#define ADC_Channel_9 ((uint8_t)0x09)
+#define ADC_Channel_10 ((uint8_t)0x0A)
+#define ADC_Channel_11 ((uint8_t)0x0B)
+#define ADC_Channel_12 ((uint8_t)0x0C)
+#define ADC_Channel_13 ((uint8_t)0x0D)
+#define ADC_Channel_14 ((uint8_t)0x0E)
+#define ADC_Channel_15 ((uint8_t)0x0F)
+#define ADC_Channel_16 ((uint8_t)0x10)
+#define ADC_Channel_17 ((uint8_t)0x11)
+#define ADC_Channel_18 ((uint8_t)0x12)
+
+#if defined (STM32F40_41xxx)
+#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_16)
+#endif /* STM32F40_41xxx */
+
+#if defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx)
+#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_18)
+#endif /* STM32F427_437xx || STM32F429_439xx || STM32F401xx */
+
+#define ADC_Channel_Vrefint ((uint8_t)ADC_Channel_17)
+#define ADC_Channel_Vbat ((uint8_t)ADC_Channel_18)
+
+#define IS_ADC_CHANNEL(CHANNEL) (((CHANNEL) == ADC_Channel_0) || \
+ ((CHANNEL) == ADC_Channel_1) || \
+ ((CHANNEL) == ADC_Channel_2) || \
+ ((CHANNEL) == ADC_Channel_3) || \
+ ((CHANNEL) == ADC_Channel_4) || \
+ ((CHANNEL) == ADC_Channel_5) || \
+ ((CHANNEL) == ADC_Channel_6) || \
+ ((CHANNEL) == ADC_Channel_7) || \
+ ((CHANNEL) == ADC_Channel_8) || \
+ ((CHANNEL) == ADC_Channel_9) || \
+ ((CHANNEL) == ADC_Channel_10) || \
+ ((CHANNEL) == ADC_Channel_11) || \
+ ((CHANNEL) == ADC_Channel_12) || \
+ ((CHANNEL) == ADC_Channel_13) || \
+ ((CHANNEL) == ADC_Channel_14) || \
+ ((CHANNEL) == ADC_Channel_15) || \
+ ((CHANNEL) == ADC_Channel_16) || \
+ ((CHANNEL) == ADC_Channel_17) || \
+ ((CHANNEL) == ADC_Channel_18))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_sampling_times
+ * @{
+ */
+#define ADC_SampleTime_3Cycles ((uint8_t)0x00)
+#define ADC_SampleTime_15Cycles ((uint8_t)0x01)
+#define ADC_SampleTime_28Cycles ((uint8_t)0x02)
+#define ADC_SampleTime_56Cycles ((uint8_t)0x03)
+#define ADC_SampleTime_84Cycles ((uint8_t)0x04)
+#define ADC_SampleTime_112Cycles ((uint8_t)0x05)
+#define ADC_SampleTime_144Cycles ((uint8_t)0x06)
+#define ADC_SampleTime_480Cycles ((uint8_t)0x07)
+#define IS_ADC_SAMPLE_TIME(TIME) (((TIME) == ADC_SampleTime_3Cycles) || \
+ ((TIME) == ADC_SampleTime_15Cycles) || \
+ ((TIME) == ADC_SampleTime_28Cycles) || \
+ ((TIME) == ADC_SampleTime_56Cycles) || \
+ ((TIME) == ADC_SampleTime_84Cycles) || \
+ ((TIME) == ADC_SampleTime_112Cycles) || \
+ ((TIME) == ADC_SampleTime_144Cycles) || \
+ ((TIME) == ADC_SampleTime_480Cycles))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_external_trigger_edge_for_injected_channels_conversion
+ * @{
+ */
+#define ADC_ExternalTrigInjecConvEdge_None ((uint32_t)0x00000000)
+#define ADC_ExternalTrigInjecConvEdge_Rising ((uint32_t)0x00100000)
+#define ADC_ExternalTrigInjecConvEdge_Falling ((uint32_t)0x00200000)
+#define ADC_ExternalTrigInjecConvEdge_RisingFalling ((uint32_t)0x00300000)
+#define IS_ADC_EXT_INJEC_TRIG_EDGE(EDGE) (((EDGE) == ADC_ExternalTrigInjecConvEdge_None) || \
+ ((EDGE) == ADC_ExternalTrigInjecConvEdge_Rising) || \
+ ((EDGE) == ADC_ExternalTrigInjecConvEdge_Falling) || \
+ ((EDGE) == ADC_ExternalTrigInjecConvEdge_RisingFalling))
+
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_extrenal_trigger_sources_for_injected_channels_conversion
+ * @{
+ */
+#define ADC_ExternalTrigInjecConv_T1_CC4 ((uint32_t)0x00000000)
+#define ADC_ExternalTrigInjecConv_T1_TRGO ((uint32_t)0x00010000)
+#define ADC_ExternalTrigInjecConv_T2_CC1 ((uint32_t)0x00020000)
+#define ADC_ExternalTrigInjecConv_T2_TRGO ((uint32_t)0x00030000)
+#define ADC_ExternalTrigInjecConv_T3_CC2 ((uint32_t)0x00040000)
+#define ADC_ExternalTrigInjecConv_T3_CC4 ((uint32_t)0x00050000)
+#define ADC_ExternalTrigInjecConv_T4_CC1 ((uint32_t)0x00060000)
+#define ADC_ExternalTrigInjecConv_T4_CC2 ((uint32_t)0x00070000)
+#define ADC_ExternalTrigInjecConv_T4_CC3 ((uint32_t)0x00080000)
+#define ADC_ExternalTrigInjecConv_T4_TRGO ((uint32_t)0x00090000)
+#define ADC_ExternalTrigInjecConv_T5_CC4 ((uint32_t)0x000A0000)
+#define ADC_ExternalTrigInjecConv_T5_TRGO ((uint32_t)0x000B0000)
+#define ADC_ExternalTrigInjecConv_T8_CC2 ((uint32_t)0x000C0000)
+#define ADC_ExternalTrigInjecConv_T8_CC3 ((uint32_t)0x000D0000)
+#define ADC_ExternalTrigInjecConv_T8_CC4 ((uint32_t)0x000E0000)
+#define ADC_ExternalTrigInjecConv_Ext_IT15 ((uint32_t)0x000F0000)
+#define IS_ADC_EXT_INJEC_TRIG(INJTRIG) (((INJTRIG) == ADC_ExternalTrigInjecConv_T1_CC4) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T1_TRGO) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_CC1) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T2_TRGO) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC2) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T3_CC4) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC1) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC2) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_CC3) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T4_TRGO) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_CC4) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T5_TRGO) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC2) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC3) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_T8_CC4) || \
+ ((INJTRIG) == ADC_ExternalTrigInjecConv_Ext_IT15))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_injected_channel_selection
+ * @{
+ */
+#define ADC_InjectedChannel_1 ((uint8_t)0x14)
+#define ADC_InjectedChannel_2 ((uint8_t)0x18)
+#define ADC_InjectedChannel_3 ((uint8_t)0x1C)
+#define ADC_InjectedChannel_4 ((uint8_t)0x20)
+#define IS_ADC_INJECTED_CHANNEL(CHANNEL) (((CHANNEL) == ADC_InjectedChannel_1) || \
+ ((CHANNEL) == ADC_InjectedChannel_2) || \
+ ((CHANNEL) == ADC_InjectedChannel_3) || \
+ ((CHANNEL) == ADC_InjectedChannel_4))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_analog_watchdog_selection
+ * @{
+ */
+#define ADC_AnalogWatchdog_SingleRegEnable ((uint32_t)0x00800200)
+#define ADC_AnalogWatchdog_SingleInjecEnable ((uint32_t)0x00400200)
+#define ADC_AnalogWatchdog_SingleRegOrInjecEnable ((uint32_t)0x00C00200)
+#define ADC_AnalogWatchdog_AllRegEnable ((uint32_t)0x00800000)
+#define ADC_AnalogWatchdog_AllInjecEnable ((uint32_t)0x00400000)
+#define ADC_AnalogWatchdog_AllRegAllInjecEnable ((uint32_t)0x00C00000)
+#define ADC_AnalogWatchdog_None ((uint32_t)0x00000000)
+#define IS_ADC_ANALOG_WATCHDOG(WATCHDOG) (((WATCHDOG) == ADC_AnalogWatchdog_SingleRegEnable) || \
+ ((WATCHDOG) == ADC_AnalogWatchdog_SingleInjecEnable) || \
+ ((WATCHDOG) == ADC_AnalogWatchdog_SingleRegOrInjecEnable) || \
+ ((WATCHDOG) == ADC_AnalogWatchdog_AllRegEnable) || \
+ ((WATCHDOG) == ADC_AnalogWatchdog_AllInjecEnable) || \
+ ((WATCHDOG) == ADC_AnalogWatchdog_AllRegAllInjecEnable) || \
+ ((WATCHDOG) == ADC_AnalogWatchdog_None))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_interrupts_definition
+ * @{
+ */
+#define ADC_IT_EOC ((uint16_t)0x0205)
+#define ADC_IT_AWD ((uint16_t)0x0106)
+#define ADC_IT_JEOC ((uint16_t)0x0407)
+#define ADC_IT_OVR ((uint16_t)0x201A)
+#define IS_ADC_IT(IT) (((IT) == ADC_IT_EOC) || ((IT) == ADC_IT_AWD) || \
+ ((IT) == ADC_IT_JEOC)|| ((IT) == ADC_IT_OVR))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_flags_definition
+ * @{
+ */
+#define ADC_FLAG_AWD ((uint8_t)0x01)
+#define ADC_FLAG_EOC ((uint8_t)0x02)
+#define ADC_FLAG_JEOC ((uint8_t)0x04)
+#define ADC_FLAG_JSTRT ((uint8_t)0x08)
+#define ADC_FLAG_STRT ((uint8_t)0x10)
+#define ADC_FLAG_OVR ((uint8_t)0x20)
+
+#define IS_ADC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint8_t)0xC0) == 0x00) && ((FLAG) != 0x00))
+#define IS_ADC_GET_FLAG(FLAG) (((FLAG) == ADC_FLAG_AWD) || \
+ ((FLAG) == ADC_FLAG_EOC) || \
+ ((FLAG) == ADC_FLAG_JEOC) || \
+ ((FLAG)== ADC_FLAG_JSTRT) || \
+ ((FLAG) == ADC_FLAG_STRT) || \
+ ((FLAG)== ADC_FLAG_OVR))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_thresholds
+ * @{
+ */
+#define IS_ADC_THRESHOLD(THRESHOLD) ((THRESHOLD) <= 0xFFF)
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_injected_offset
+ * @{
+ */
+#define IS_ADC_OFFSET(OFFSET) ((OFFSET) <= 0xFFF)
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_injected_length
+ * @{
+ */
+#define IS_ADC_INJECTED_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x4))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_injected_rank
+ * @{
+ */
+#define IS_ADC_INJECTED_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x4))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_regular_length
+ * @{
+ */
+#define IS_ADC_REGULAR_LENGTH(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x10))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_regular_rank
+ * @{
+ */
+#define IS_ADC_REGULAR_RANK(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10))
+/**
+ * @}
+ */
+
+
+/** @defgroup ADC_regular_discontinuous_mode_number
+ * @{
+ */
+#define IS_ADC_REGULAR_DISC_NUMBER(NUMBER) (((NUMBER) >= 0x1) && ((NUMBER) <= 0x8))
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/* Function used to set the ADC configuration to the default reset state *****/
+void ADC_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
+void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);
+void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
+void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
+void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+
+/* Analog Watchdog configuration functions ************************************/
+void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
+void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold);
+void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);
+
+/* Temperature Sensor, Vrefint and VBAT management functions ******************/
+void ADC_TempSensorVrefintCmd(FunctionalState NewState);
+void ADC_VBATCmd(FunctionalState NewState);
+
+/* Regular Channels Configuration functions ***********************************/
+void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
+void ADC_SoftwareStartConv(ADC_TypeDef* ADCx);
+FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
+void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
+void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
+uint32_t ADC_GetMultiModeConversionValue(void);
+
+/* Regular Channels DMA Configuration functions *******************************/
+void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState NewState);
+
+/* Injected channels Configuration functions **********************************/
+void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
+void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
+void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
+void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
+void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge);
+void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx);
+FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
+void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
+uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
+
+/* Interrupts and flags management functions **********************************/
+void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
+FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
+void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
+ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
+void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F4xx_ADC_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm/lib/usb_bsp.c b/stm/lib/usb_bsp.c index c4839bdf96..e88e31db0e 100644 --- a/stm/lib/usb_bsp.c +++ b/stm/lib/usb_bsp.c @@ -117,6 +117,17 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) { GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
+ /*
+ // Configure ID pin (only in host mode)
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+ GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_OTG_FS);
+ */
+
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE);
}
@@ -138,6 +149,84 @@ void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev) { }
/**
+* @brief BSP_Drive_VBUS
+* Drives the Vbus signal through IO
+* @param state : VBUS states
+* @retval None
+*/
+
+void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev, uint8_t state) {
+ //printf("DriveVBUS %p %u\n", pdev, state);
+ /*
+ On-chip 5 V VBUS generation is not supported. For this reason, a charge pump
+ or, if 5 V are available on the application board, a basic power switch, must
+ be added externally to drive the 5 V VBUS line. The external charge pump can
+ be driven by any GPIO output. When the application decides to power on VBUS
+ using the chosen GPIO, it must also set the port power bit in the host port
+ control and status register (PPWR bit in OTG_FS_HPRT).
+
+ Bit 12 PPWR: Port power
+ The application uses this field to control power to this port, and the core
+ clears this bit on an overcurrent condition.
+ */
+#if 0 // not implemented
+#ifndef USE_USB_OTG_HS
+ if (0 == state) {
+ /* DISABLE is needed on output of the Power Switch */
+ GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
+ } else {
+ /*ENABLE the Power Switch by driving the Enable LOW */
+ GPIO_ResetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
+ }
+#endif
+#endif
+}
+
+/**
+ * @brief USB_OTG_BSP_ConfigVBUS
+ * Configures the IO for the Vbus and OverCurrent
+ * @param None
+ * @retval None
+ */
+
+void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev) {
+ //printf("ConfigVBUS %p\n", pdev);
+#if 0 // not implemented
+#ifdef USE_USB_OTG_FS
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+#ifdef USE_STM3210C_EVAL
+ RCC_APB2PeriphClockCmd(HOST_POWERSW_PORT_RCC, ENABLE);
+
+
+ /* Configure Power Switch Vbus Pin */
+ GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+ GPIO_Init(HOST_POWERSW_PORT, &GPIO_InitStructure);
+#else
+ #ifdef USE_USB_OTG_FS
+ RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOH , ENABLE);
+
+ GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
+ GPIO_Init(HOST_POWERSW_PORT,&GPIO_InitStructure);
+ #endif
+#endif
+
+ /* By Default, DISABLE is needed on output of the Power Switch */
+ GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
+
+ USB_OTG_BSP_mDelay(200); /* Delay is need for stabilising the Vbus Low
+ in Reset Condition, when Vbus=1 and Reset-button is pressed by user */
+#endif
+#endif
+}
+
+/**
* @brief USB_OTG_BSP_uDelay
* This function provides delay time in micro sec
* @param usec : Value of delay required in micro sec
diff --git a/stm/lib/usb_conf.h b/stm/lib/usb_conf.h index 5e736f91e2..a51a23a84e 100644 --- a/stm/lib/usb_conf.h +++ b/stm/lib/usb_conf.h @@ -181,10 +181,65 @@ /****************** USB OTG MISC CONFIGURATION ********************************/
#define VBUS_SENSING_ENABLED
+/* BEGIN host specific stuff */
+
+/*******************************************************************************
+* FIFO Size Configuration in Host mode
+*
+* (i) Receive data FIFO size = (Largest Packet Size / 4) + 1 or
+* 2x (Largest Packet Size / 4) + 1, If a
+* high-bandwidth channel or multiple isochronous
+* channels are enabled
+*
+* (ii) For the host nonperiodic Transmit FIFO is the largest maximum packet size
+* for all supported nonperiodic OUT channels. Typically, a space
+* corresponding to two Largest Packet Size is recommended.
+*
+* (iii) The minimum amount of RAM required for Host periodic Transmit FIFO is
+* the largest maximum packet size for all supported periodic OUT channels.
+* If there is at least one High Bandwidth Isochronous OUT endpoint,
+* then the space must be at least two times the maximum packet size for
+* that channel.
+*******************************************************************************/
+
+/****************** USB OTG HS CONFIGURATION (for host) ***********************/
+#ifdef USB_OTG_HS_CORE
+ #define RX_FIFO_HS_SIZE 512
+ #define TXH_NP_HS_FIFOSIZ 256
+ #define TXH_P_HS_FIFOSIZ 256
+
+// #define USB_OTG_HS_LOW_PWR_MGMT_SUPPORT
+// #define USB_OTG_HS_SOF_OUTPUT_ENABLED
+
+// #define USB_OTG_INTERNAL_VBUS_ENABLED
+#define USB_OTG_EXTERNAL_VBUS_ENABLED
+
+ #ifdef USE_ULPI_PHY
+ #define USB_OTG_ULPI_PHY_ENABLED
+ #endif
+ #ifdef USE_EMBEDDED_PHY
+ #define USB_OTG_EMBEDDED_PHY_ENABLED
+ #endif
+ #define USB_OTG_HS_INTERNAL_DMA_ENABLED
+// #define USB_OTG_HS_DEDICATED_EP1_ENABLED
+#endif
+
+/****************** USB OTG FS CONFIGURATION (for host) ***********************/
+#ifdef USB_OTG_FS_CORE
+ //#define RX_FIFO_FS_SIZE 128 // already defined for device (and it's the same)
+ #define TXH_NP_FS_FIFOSIZ 96
+ #define TXH_P_FS_FIFOSIZ 96
+
+// #define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
+// #define USB_OTG_FS_SOF_OUTPUT_ENABLED
+#endif
+
+/* END host specific stuff */
+
/****************** USB OTG MODE CONFIGURATION ********************************/
-//#define USE_HOST_MODE
+//#define USE_HOST_MODE // set in Makefile
#define USE_DEVICE_MODE
-//#define USE_OTG_MODE
+//#define USE_OTG_MODE // set in Makefile
#ifndef USB_OTG_FS_CORE
#ifndef USB_OTG_HS_CORE
diff --git a/stm/lib/usb_core.c b/stm/lib/usb_core.c index 4b28c085f2..b0cce88046 100644 --- a/stm/lib/usb_core.c +++ b/stm/lib/usb_core.c @@ -617,7 +617,7 @@ USB_OTG_STS USB_OTG_CoreInitHost(USB_OTG_CORE_HANDLE *pdev) USB_OTG_HCFG_TypeDef hcfg;
#ifdef USE_OTG_MODE
- USB_OTG_OTGCTL_TypeDef gotgctl;
+ USB_OTG_GOTGCTL_TypeDef gotgctl;
#endif
uint32_t i = 0;
diff --git a/stm/main.c b/stm/main.c index 44db47f13b..d8649f5797 100644 --- a/stm/main.c +++ b/stm/main.c @@ -40,6 +40,7 @@ #include "pybwlan.h" #include "i2c.h" #include "usrsw.h" +#include "adc.h" int errno; @@ -307,7 +308,9 @@ char *strdup(const char *str) { static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; void stdout_tx_str(const char *str) { - //usart_tx_str(str); // disabled because usart is a Python object and we now need specify which USART port + if (pyb_usart_global_debug != PYB_USART_NONE) { + usart_tx_str(pyb_usart_global_debug, str); + } usb_vcp_send_str(str); } @@ -322,10 +325,10 @@ int readline(vstr_t *line, const char *prompt) { if (usb_vcp_rx_any() != 0) { c = usb_vcp_rx_get(); break; - } /*else if (usart_rx_any()) { // disabled because usart is a Python object and we now need specify which USART port - c = usart_rx_char(); + } else if (pyb_usart_global_debug != PYB_USART_NONE && usart_rx_any(pyb_usart_global_debug)) { + c = usart_rx_char(pyb_usart_global_debug); break; - }*/ + } sys_tick_delay_ms(1); if (storage_needs_flush()) { storage_flush(); @@ -388,7 +391,7 @@ void do_repl(void) { stdout_tx_str("Type \"help()\" for more information.\r\n"); vstr_t line; - vstr_init(&line); + vstr_init(&line, 32); for (;;) { vstr_reset(&line); @@ -415,10 +418,18 @@ void do_repl(void) { } mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), 0); - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT); - mp_lexer_free(lex); - - if (pn != MP_PARSE_NODE_NULL) { + qstr parse_exc_id; + const char *parse_exc_msg; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_exc_id, &parse_exc_msg); + + if (pn == MP_PARSE_NODE_NULL) { + // parse error + mp_lexer_show_error_pythonic_prefix(lex); + printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_lexer_free(lex); + } else { + // parse okay + mp_lexer_free(lex); mp_obj_t module_fun = mp_compile(pn, true); if (module_fun != mp_const_none) { nlr_buf_t nlr; @@ -433,7 +444,7 @@ void do_repl(void) { } } else { // uncaught exception - mp_obj_print((mp_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR); printf("\n"); } } @@ -452,13 +463,20 @@ bool do_file(const char *filename) { return false; } - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_lexer_free(lex); + qstr parse_exc_id; + const char *parse_exc_msg; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); if (pn == MP_PARSE_NODE_NULL) { + // parse error + mp_lexer_show_error_pythonic_prefix(lex); + printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_lexer_free(lex); return false; } + mp_lexer_free(lex); + mp_obj_t module_fun = mp_compile(pn, false); if (module_fun == mp_const_none) { return false; @@ -471,7 +489,7 @@ bool do_file(const char *filename) { return true; } else { // uncaught exception - mp_obj_print((mp_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR); printf("\n"); return false; } @@ -653,7 +671,7 @@ typedef struct _pyb_file_obj_t { FIL fp; } pyb_file_obj_t; -void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { printf("<file %p>", self_in); } @@ -775,7 +793,9 @@ int main(void) { switch_init(); storage_init(); - //usart_init(); disabled while wi-fi is enabled; also disabled because now usart is a proper Python object + // uncomment these 2 lines if you want REPL on USART_6 (or another usart) as well as on USB VCP + //pyb_usart_global_debug = PYB_USART_6; + //usart_init(pyb_usart_global_debug, 115200); int first_soft_reset = true; @@ -808,36 +828,37 @@ soft_reset: // add some functions to the python namespace { - rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help)); + rt_store_name(qstr_from_str_static("help"), rt_make_function_n(0, pyb_help)); mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb")); - rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info)); - rt_store_attr(m, qstr_from_str_static("sd_test"), rt_make_function_0(pyb_sd_test)); - rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_0(pyb_stop)); - rt_store_attr(m, qstr_from_str_static("standby"), rt_make_function_0(pyb_standby)); - rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_1(pyb_source_dir)); - rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_1(pyb_main)); - rt_store_attr(m, qstr_from_str_static("sync"), rt_make_function_0(pyb_sync)); - rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_0(pyb_gc)); - rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay)); - rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led)); + rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_n(0, pyb_info)); + rt_store_attr(m, qstr_from_str_static("sd_test"), rt_make_function_n(0, pyb_sd_test)); + rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_n(0, pyb_stop)); + rt_store_attr(m, qstr_from_str_static("standby"), rt_make_function_n(0, pyb_standby)); + rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_n(1, pyb_source_dir)); + rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_n(1, pyb_main)); + rt_store_attr(m, qstr_from_str_static("sync"), rt_make_function_n(0, pyb_sync)); + rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_n(0, pyb_gc)); + rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_n(1, pyb_delay)); + rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_n(1, pyb_led)); rt_store_attr(m, qstr_from_str_static("switch"), (mp_obj_t)&pyb_switch_obj); - rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_2(pyb_servo_set)); - rt_store_attr(m, qstr_from_str_static("pwm"), rt_make_function_2(pyb_pwm_set)); + rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_n(2, pyb_servo_set)); + rt_store_attr(m, qstr_from_str_static("pwm"), rt_make_function_n(2, pyb_pwm_set)); rt_store_attr(m, qstr_from_str_static("accel"), (mp_obj_t)&pyb_mma_read_obj); rt_store_attr(m, qstr_from_str_static("mma_read"), (mp_obj_t)&pyb_mma_read_all_obj); rt_store_attr(m, qstr_from_str_static("mma_mode"), (mp_obj_t)&pyb_mma_write_mode_obj); - rt_store_attr(m, qstr_from_str_static("hid"), rt_make_function_1(pyb_hid_send_report)); - rt_store_attr(m, qstr_from_str_static("time"), rt_make_function_0(pyb_rtc_read)); - rt_store_attr(m, qstr_from_str_static("rand"), rt_make_function_0(pyb_rng_get)); - rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led)); - rt_store_attr(m, qstr_from_str_static("Servo"), rt_make_function_1(pyb_Servo)); - rt_store_attr(m, qstr_from_str_static("I2C"), rt_make_function_2(pyb_I2C)); + rt_store_attr(m, qstr_from_str_static("hid"), rt_make_function_n(1, pyb_hid_send_report)); + rt_store_attr(m, qstr_from_str_static("time"), rt_make_function_n(0, pyb_rtc_read)); + rt_store_attr(m, qstr_from_str_static("rand"), rt_make_function_n(0, pyb_rng_get)); + rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_n(1, pyb_Led)); + rt_store_attr(m, qstr_from_str_static("Servo"), rt_make_function_n(1, pyb_Servo)); + rt_store_attr(m, qstr_from_str_static("I2C"), rt_make_function_n(2, pyb_I2C)); rt_store_attr(m, qstr_from_str_static("gpio"), (mp_obj_t)&pyb_gpio_obj); - rt_store_attr(m, qstr_from_str_static("Usart"), rt_make_function_2(pyb_Usart)); + rt_store_attr(m, qstr_from_str_static("Usart"), rt_make_function_n(2, pyb_Usart)); + rt_store_attr(m, qstr_from_str_static("ADC"), rt_make_function_n(1, pyb_ADC)); rt_store_name(qstr_from_str_static("pyb"), m); - rt_store_name(qstr_from_str_static("open"), rt_make_function_2(pyb_io_open)); + rt_store_name(qstr_from_str_static("open"), rt_make_function_n(2, pyb_io_open)); } // print a message to the LCD @@ -937,6 +958,9 @@ soft_reset: // USB usb_init(); + // USB host; not working! + //pyb_usbh_init(); + // MMA if (first_soft_reset) { // init and reset address to zero @@ -1064,7 +1088,9 @@ soft_reset: // nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler printf("lex; al=%u\n", m_get_total_bytes_allocated()); sys_tick_delay_ms(1000); - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); + qstr parse_exc_id; + const char *parse_exc_msg; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); mp_lexer_free(lex); if (pn != MP_PARSE_NODE_NULL) { printf("pars;al=%u\n", m_get_total_bytes_allocated()); @@ -1088,13 +1114,13 @@ soft_reset: if (nlr_push(&nlr) == 0) { mp_obj_t ret = rt_call_function_0(module_fun); printf("done! got: "); - mp_obj_print(ret); + mp_obj_print(ret, PRINT_REPR); printf("\n"); nlr_pop(); } else { // uncaught exception printf("exception: "); - mp_obj_print((mp_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR); printf("\n"); } @@ -1171,6 +1197,7 @@ soft_reset: goto soft_reset; } +/* now supplied by libgcc library double __aeabi_f2d(float x) { // TODO return 0.0; @@ -1180,6 +1207,7 @@ float __aeabi_d2f(double x) { // TODO return 0.0; } +*/ double sqrt(double x) { // TODO diff --git a/stm/printf.c b/stm/printf.c index 8a40a61a5f..732e834526 100644 --- a/stm/printf.c +++ b/stm/printf.c @@ -206,6 +206,21 @@ int pfenv_printf(const pfenv_t *pfenv, const char *fmt, va_list args) { case 'P': // ? chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, width); break; + case 'g': + { + // This is a very hacky approach to printing floats. Micropython + // uses %g when using print, and I just wanted to see somthing + // usable. I expect that this will be replaced with something + // more appropriate. + char dot = '.'; + mp_float_t d = va_arg(args, double); + int left = (int)d; + int right = (int)((d - (mp_float_t)(int)d) * 1000000.0); + chrs += pfenv_print_int(pfenv, left, 1, 10, 'a', flags, width); + chrs += pfenv_print_strn(pfenv, &dot, 1, flags, width); + chrs += pfenv_print_int(pfenv, right, 0, 10, 'a', PF_FLAG_ZERO_PAD, 6); + break; + } default: pfenv->print_strn(pfenv->data, fmt, 1); chrs += 1; @@ -220,12 +235,10 @@ void stdout_print_strn(void *data, const char *str, unsigned int len) { // send stdout to USART, USB CDC VCP, and LCD if nothing else bool any = false; - // TODO should have a setting for which USART port to send to - if (usart_is_enabled()) { - usart_tx_strn_cooked(str, len); + if (pyb_usart_global_debug != PYB_USART_NONE) { + usart_tx_strn_cooked(pyb_usart_global_debug, str, len); any = true; } - if (usb_vcp_is_enabled()) { usb_vcp_send_strn_cooked(str, len); any = true; diff --git a/stm/pybwlan.c b/stm/pybwlan.c index 09d642d9c8..91d71a652b 100644 --- a/stm/pybwlan.c +++ b/stm/pybwlan.c @@ -357,11 +357,11 @@ void pyb_wlan_init(void) { mp_obj_t m = mp_obj_new_module(qstr_from_str_static("wlan")); rt_store_attr(m, qstr_from_str_static("connect"), rt_make_function_var(0, pyb_wlan_connect)); - rt_store_attr(m, qstr_from_str_static("disconnect"), rt_make_function_0(pyb_wlan_disconnect)); - rt_store_attr(m, qstr_from_str_static("ip"), rt_make_function_0(pyb_wlan_get_ip)); - rt_store_attr(m, qstr_from_str_static("get_host"), rt_make_function_1(pyb_wlan_get_host)); - rt_store_attr(m, qstr_from_str_static("http_get"), rt_make_function_2(pyb_wlan_http_get)); - rt_store_attr(m, qstr_from_str_static("serve"), rt_make_function_0(pyb_wlan_serve)); + rt_store_attr(m, qstr_from_str_static("disconnect"), rt_make_function_n(0, pyb_wlan_disconnect)); + rt_store_attr(m, qstr_from_str_static("ip"), rt_make_function_n(0, pyb_wlan_get_ip)); + rt_store_attr(m, qstr_from_str_static("get_host"), rt_make_function_n(1, pyb_wlan_get_host)); + rt_store_attr(m, qstr_from_str_static("http_get"), rt_make_function_n(2, pyb_wlan_http_get)); + rt_store_attr(m, qstr_from_str_static("serve"), rt_make_function_n(0, pyb_wlan_serve)); rt_store_name(qstr_from_str_static("wlan"), m); } @@ -17,6 +17,8 @@ int strncmp(const char *s1, const char *s2, size_t n); char *strndup(const char *s, size_t n); char *strcpy(char *dest, const char *src); char *strcat(char *dest, const char *src); +char *strchr(const char *s, int c); +char *strstr(const char *haystack, const char *needle); int printf(const char *fmt, ...); int snprintf(char *str, size_t size, const char *fmt, ...); diff --git a/stm/stm32fxxx_it.c b/stm/stm32fxxx_it.c index e254ccc899..c1a9a0702f 100644 --- a/stm/stm32fxxx_it.c +++ b/stm/stm32fxxx_it.c @@ -31,6 +31,7 @@ #include "stm32fxxx_it.h" #include "stm32f4xx_exti.h" #include "usb_core.h" +//#include "usb_hcd_int.h" // for usb host mode only //#include "usbd_core.h" //#include "usbd_cdc_core.h" @@ -197,7 +198,8 @@ void OTG_HS_IRQHandler(void) void OTG_FS_IRQHandler(void) #endif { - USBD_OTG_ISR_Handler (&USB_OTG_dev); + USBD_OTG_ISR_Handler (&USB_OTG_dev); // device mode + //USBH_OTG_ISR_Handler (&USB_OTG_dev); // host mode FIXME } #ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED diff --git a/stm/string0.c b/stm/string0.c index 2a5f255971..d67c5f2b17 100644 --- a/stm/string0.c +++ b/stm/string0.c @@ -108,3 +108,31 @@ char *strcat(char *dest, const char *src) { *d = '\0'; return dest; } + +// Public Domain implementation of strchr from: +// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strchr_function +char *strchr(const char *s, int c) +{ + /* Scan s for the character. When this loop is finished, + s will either point to the end of the string or the + character we were looking for. */ + while (*s != '\0' && *s != (char)c) + s++; + return ((*s == c) ? (char *) s : 0); +} + + +// Public Domain implementation of strstr from: +// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strstr_function +char *strstr(const char *haystack, const char *needle) +{ + size_t needlelen; + /* Check for the null needle case. */ + if (*needle == '\0') + return (char *) haystack; + needlelen = strlen(needle); + for (; (haystack = strchr(haystack, *needle)) != 0; haystack++) + if (strncmp(haystack, needle, needlelen) == 0) + return (char *) haystack; + return 0; +} diff --git a/stm/timer.c b/stm/timer.c index 2605d4b4bc..062f8c689e 100644 --- a/stm/timer.c +++ b/stm/timer.c @@ -72,10 +72,10 @@ void timer_init(void) { // Python interface mp_obj_t m = mp_obj_new_module(qstr_from_str_static("timer")); - rt_store_attr(m, qstr_from_str_static("callback"), rt_make_function_1(timer_py_set_callback)); - rt_store_attr(m, qstr_from_str_static("period"), rt_make_function_1(timer_py_set_period)); - rt_store_attr(m, qstr_from_str_static("prescaler"), rt_make_function_1(timer_py_set_prescaler)); - rt_store_attr(m, qstr_from_str_static("value"), rt_make_function_0(timer_py_get_value)); + rt_store_attr(m, qstr_from_str_static("callback"), rt_make_function_n(1, timer_py_set_callback)); + rt_store_attr(m, qstr_from_str_static("period"), rt_make_function_n(1, timer_py_set_period)); + rt_store_attr(m, qstr_from_str_static("prescaler"), rt_make_function_n(1, timer_py_set_prescaler)); + rt_store_attr(m, qstr_from_str_static("value"), rt_make_function_n(0, timer_py_get_value)); rt_store_name(qstr_from_str_static("timer"), m); } @@ -89,7 +89,7 @@ void timer_interrupt(void) { } else { // uncaught exception printf("exception in timer interrupt\n"); - mp_obj_print((mp_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR); printf("\n"); } } diff --git a/stm/usart.c b/stm/usart.c index bc5bfc7369..5f47ec788a 100644 --- a/stm/usart.c +++ b/stm/usart.c @@ -8,20 +8,14 @@ #include "obj.h" #include "usart.h" -static bool is_enabled; - -typedef enum { - PYB_USART_1 = 1, - PYB_USART_2 = 2, - PYB_USART_3 = 3, - PYB_USART_6 = 4, - PYB_USART_MAX = 4, -} pyb_usart_t; +pyb_usart_t pyb_usart_global_debug = PYB_USART_NONE; static USART_TypeDef *usart_get_base(pyb_usart_t usart_id) { USART_TypeDef *USARTx=NULL; switch (usart_id) { + case PYB_USART_NONE: + break; case PYB_USART_1: USARTx = USART1; break; @@ -52,6 +46,9 @@ void usart_init(pyb_usart_t usart_id, uint32_t baudrate) { void (*RCC_APBxPeriphClockCmd)(uint32_t, FunctionalState)=NULL; switch (usart_id) { + case PYB_USART_NONE: + return; + case PYB_USART_1: USARTx = USART1; @@ -128,16 +125,13 @@ void usart_init(pyb_usart_t usart_id, uint32_t baudrate) { USART_Cmd(USARTx, ENABLE); } -bool usart_is_enabled(void) { - return is_enabled; -} - -bool usart_rx_any(void) { - return USART_GetFlagStatus(USART6, USART_FLAG_RXNE) == SET; +bool usart_rx_any(pyb_usart_t usart_id) { + USART_TypeDef *USARTx = usart_get_base(usart_id); + return USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == SET; } int usart_rx_char(pyb_usart_t usart_id) { - USART_TypeDef *USARTx= usart_get_base(usart_id); + USART_TypeDef *USARTx = usart_get_base(usart_id); return USART_ReceiveData(USARTx); } @@ -176,8 +170,8 @@ typedef struct _pyb_usart_obj_t { } pyb_usart_obj_t; static mp_obj_t usart_obj_status(mp_obj_t self_in) { - // TODO make it check the correct USART port! - if (usart_rx_any()) { + pyb_usart_obj_t *self = self_in; + if (usart_rx_any(self->usart_id)) { return mp_const_true; } else { return mp_const_false; diff --git a/stm/usart.h b/stm/usart.h index 15ed419fe7..541cb757c8 100644 --- a/stm/usart.h +++ b/stm/usart.h @@ -1 +1,18 @@ +typedef enum { + PYB_USART_NONE = 0, + PYB_USART_1 = 1, + PYB_USART_2 = 2, + PYB_USART_3 = 3, + PYB_USART_6 = 4, + PYB_USART_MAX = 4, +} pyb_usart_t; + +extern pyb_usart_t pyb_usart_global_debug; + +void usart_init(pyb_usart_t usart_id, uint32_t baudrate); +bool usart_rx_any(pyb_usart_t usart_id); +int usart_rx_char(pyb_usart_t usart_id); +void usart_tx_str(pyb_usart_t usart_id, const char *str); +void usart_tx_strn_cooked(pyb_usart_t usart_id, const char *str, int len); + mp_obj_t pyb_Usart(mp_obj_t usart_id, mp_obj_t baudrate); @@ -80,7 +80,7 @@ void usb_vcp_send_strn(const char *str, int len) { } } -#include "lib/usbd_conf.h" +#include "usbd_conf.h" /* These are external variables imported from CDC core to be used for IN transfer management. */ @@ -105,3 +105,30 @@ void usb_vcp_send_strn_cooked(const char *str, int len) { void usb_hid_send_report(uint8_t *buf) { USBD_HID_SendReport(&USB_OTG_dev, buf, 4); } + +/******************************************************************************/ +// code for experimental USB OTG support + +#ifdef USE_HOST_MODE + +#include "lib-otg/usbh_core.h" +#include "lib-otg/usbh_usr.h" +#include "lib-otg/usbh_hid_core.h" + +__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ; + +static int host_is_enabled = 0; +void pyb_usbh_init(void) { + if (!host_is_enabled) { + // only init USBH once in the device's power-lifetime + /* Init Host Library */ + USBH_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks); + } + host_is_enabled = 1; +} + +void pyb_usbh_process(void) { + USBH_Process(&USB_OTG_dev, &USB_Host); +} + +#endif // USE_HOST_MODE @@ -6,3 +6,6 @@ void usb_vcp_send_str(const char* str); void usb_vcp_send_strn(const char* str, int len); void usb_vcp_send_strn_cooked(const char *str, int len); void usb_hid_send_report(uint8_t *buf); // 4 bytes for mouse: ?, x, y, ? + +void pyb_usbh_init(void); +void pyb_usbh_process(void); diff --git a/teensy/Makefile b/teensy/Makefile index ade9b37040..e25f81481f 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -24,16 +24,27 @@ SIZE = $(COMPILER_PATH)/arm-none-eabi-size CFLAGS_TEENSY = -DF_CPU=96000000 -DUSB_SERIAL -D__MK20DX256__ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -fsingle-precision-constant -Wdouble-promotion $(CFLAGS_TEENSY) -CFLAGS = -I. -I$(PY_SRC) -I$(CORE_PATH) -Wall -ansi -std=gnu99 -Os -DNDEBUG $(CFLAGS_CORTEX_M4) -D$(TARGET) +CFLAGS = -I. -I$(PY_SRC) -I$(CORE_PATH) -Wall -ansi -std=gnu99 LDFLAGS = -nostdlib -T mk20dx256.ld LIBS = -L $(COMPILER_PATH)/../lib/gcc/arm-none-eabi/4.7.2/thumb2 -lgcc +#Debugging/Optimization +ifdef DEBUG +CFLAGS += -Og -ggdb +else +CFLAGS += -Os #-DNDEBUG +endif + +# if order is not important for these, move them up +CFLAGS += $(CFLAGS_CORTEX_M4) -D$(TARGET) + SRC_C = \ main.c \ lcd.c \ led.c \ lexerfatfs.c \ - usart.c \ + lexermemzip.c \ + memzip.c \ usb.c \ STM_SRC_C = \ @@ -60,9 +71,9 @@ OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o #LIB += -ltermcap all2: $(BUILD) hex -hex: $(BUILD)/flash.hex +hex: $(BUILD)/micropython-mz.hex -post_compile: $(BUILD)/flash.hex +post_compile: $(BUILD)/micropython-mz.hex $(ECHO) "Preparing $@ for upload" $(Q)$(TOOLS_PATH)/teensy_post_compile -file="$(basename $(<F))" -path="$(<D)" -tools="$(TOOLS_PATH)" @@ -72,11 +83,19 @@ reboot: upload: post_compile reboot -$(BUILD)/flash.elf: $(OBJ) +$(BUILD)/micropython.elf: $(OBJ) $(ECHO) "LINK $<" $(Q)$(CC) $(LDFLAGS) -o "$@" -Wl,-Map,$(@:.elf=.map) $(OBJ) $(LIBS) $(Q)$(SIZE) $@ +ifeq ($(MEMZIP_DIR),) +MEMZIP_DIR = memzip_files +endif + +$(BUILD)/micropython-mz.hex: $(BUILD)/micropython.hex $(shell find ${MEMZIP_DIR} -type f) + @$(ECHO) "Creating $@" + $(Q)./add-memzip.sh $< $@ ${MEMZIP_DIR} + $(BUILD)/%.hex: $(BUILD)/%.elf $(ECHO) "HEX $<" $(Q)$(OBJCOPY) -O ihex -R .eeprom "$<" "$@" diff --git a/teensy/add-memzip.sh b/teensy/add-memzip.sh new file mode 100755 index 0000000000..a00489effd --- /dev/null +++ b/teensy/add-memzip.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ "$#" != 3 ]; then + echo "Usage: add-memzip.sh input.hex output.hex file-directory" + exit 1 +fi + +#set -x + +input_hex=$1 +output_hex=$2 +memzip_src_dir=$3 + +input_bin=${input_hex}.bin +output_bin=${output_hex}.bin +zip_file=${output_hex}.zip +zip_base=$(basename ${zip_file}) +zip_dir=$(dirname ${zip_file}) +abs_zip_dir=$(realpath ${zip_dir}) + +rm -f ${zip_file} +(cd ${memzip_src_dir}; zip -0 -r -D ${abs_zip_dir}/${zip_base} .) +objcopy -I ihex -O binary ${input_hex} ${input_bin} +cat ${input_bin} ${zip_file} > ${output_bin} +objcopy -I binary -O ihex ${output_bin} ${output_hex} +echo "Added ${memzip_src_dir} to ${input_hex} creating ${output_hex}" + diff --git a/teensy/lexermemzip.c b/teensy/lexermemzip.c new file mode 100644 index 0000000000..2f808ee429 --- /dev/null +++ b/teensy/lexermemzip.c @@ -0,0 +1,18 @@ +#include <stdint.h> +#include <stdlib.h> + +#include "misc.h" +#include "lexer.h" +#include "memzip.h" + +mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename) +{ + void *data; + size_t len; + + if (memzip_locate(filename, &data, &len) != MZ_OK) { + return NULL; + } + return mp_lexer_new_from_str_len(filename, (const char *)data, (uint)len, 0); +} + diff --git a/teensy/lexermemzip.h b/teensy/lexermemzip.h new file mode 100644 index 0000000000..e5d4be5eae --- /dev/null +++ b/teensy/lexermemzip.h @@ -0,0 +1,2 @@ +mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename); + diff --git a/teensy/main.c b/teensy/main.c index fd5aec0459..d5860cd9d4 100644 --- a/teensy/main.c +++ b/teensy/main.c @@ -8,6 +8,7 @@ #include "mpconfig.h" #include "mpqstr.h" #include "lexer.h" +#include "lexermemzip.h" #include "parse.h" #include "obj.h" #include "compile.h" @@ -22,52 +23,17 @@ extern uint32_t _heap_start; -#ifdef USE_READLINE -#include <readline/readline.h> -#include <readline/history.h> -#endif +bool do_file(const char *filename); -#if 0 -static char *str_join(const char *s1, int sep_char, const char *s2) { - int l1 = strlen(s1); - int l2 = strlen(s2); - char *s = m_new(char, l1 + l2 + 2); - memcpy(s, s1, l1); - if (sep_char != 0) { - s[l1] = sep_char; - l1 += 1; +void flash_error(int n) { + for (int i = 0; i < n; i++) { + led_state(PYB_LED_BUILTIN, 1); + delay(250); + led_state(PYB_LED_BUILTIN, 0); + delay(250); } - memcpy(s + l1, s2, l2); - s[l1 + l2] = 0; - return s; } -static char *prompt(char *p) { -#ifdef USE_READLINE - char *line = readline(p); - if (line) { - add_history(line); - } -#else - static char buf[256]; - fputs(p, stdout); - char *s = fgets(buf, sizeof(buf), stdin); - if (!s) { - return NULL; - } - int l = strlen(buf); - if (buf[l - 1] == '\n') { - buf[l - 1] = 0; - } else { - l++; - } - char *line = m_new(char, l); - memcpy(line, buf, l); -#endif - return line; -} -#endif - static const char *help_text = "Welcome to Micro Python!\n\n" "This is a *very* early version of Micro Python and has minimal functionality.\n\n" @@ -215,6 +181,19 @@ mp_obj_t pyb_hid_send_report(mp_obj_t arg) { } #endif +static qstr pyb_config_source_dir = 0; +static qstr pyb_config_main = 0; + +mp_obj_t pyb_source_dir(mp_obj_t source_dir) { + pyb_config_source_dir = mp_obj_get_qstr(source_dir); + return mp_const_none; +} + +mp_obj_t pyb_main(mp_obj_t main) { + pyb_config_main = mp_obj_get_qstr(main); + return mp_const_none; +} + mp_obj_t pyb_delay(mp_obj_t count) { delay(mp_obj_get_int(count)); return mp_const_none; @@ -225,6 +204,12 @@ mp_obj_t pyb_led(mp_obj_t state) { return state; } +mp_obj_t pyb_run(mp_obj_t filename_obj) { + const char *filename = qstr_str(mp_obj_get_qstr(filename_obj)); + do_file(filename); + return mp_const_none; +} + char *strdup(const char *str) { uint32_t len = strlen(str); char *s2 = m_new(char, len + 1); @@ -316,6 +301,39 @@ int readline(vstr_t *line, const char *prompt) { } } +bool do_file(const char *filename) { + mp_lexer_t *lex = mp_lexer_new_from_memzip_file(filename); + + if (lex == NULL) { + printf("could not open file '%s' for reading\n", filename); + return false; + } + + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); + mp_lexer_free(lex); + + if (pn == MP_PARSE_NODE_NULL) { + return false; + } + + mp_obj_t module_fun = mp_compile(pn, false); + if (module_fun == mp_const_none) { + return false; + } + + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + rt_call_function_0(module_fun); + nlr_pop(); + return true; + } else { + // uncaught exception + mp_obj_print((mp_obj_t)nlr.ret_val); + printf("\n"); + return false; + } +} + void do_repl(void) { stdout_tx_str("Micro Python for Teensy 3.1\r\n"); stdout_tx_str("Type \"help()\" for more information.\r\n"); @@ -397,24 +415,53 @@ soft_reset: rt_init(); #if 1 - printf("About to add functions()\n"); // add some functions to the python namespace { rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help)); mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb")); rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info)); + rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_1(pyb_source_dir)); + rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_1(pyb_main)); rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_0(pyb_gc)); rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay)); rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led)); rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led)); rt_store_attr(m, qstr_from_str_static("gpio"), (mp_obj_t)&pyb_gpio_obj); rt_store_name(qstr_from_str_static("pyb"), m); + rt_store_name(qstr_from_str_static("run"), rt_make_function_1(pyb_run)); } #endif + if (!do_file("/boot.py")) { + printf("Unable to open '/boot.py'\n"); + flash_error(4); + } + // Turn bootup LED off led_state(PYB_LED_BUILTIN, 0); + // run main script + { + vstr_t *vstr = vstr_new(); + vstr_add_str(vstr, "/"); + if (pyb_config_source_dir == 0) { + vstr_add_str(vstr, "src"); + } else { + vstr_add_str(vstr, qstr_str(pyb_config_source_dir)); + } + vstr_add_char(vstr, '/'); + if (pyb_config_main == 0) { + vstr_add_str(vstr, "main.py"); + } else { + vstr_add_str(vstr, qstr_str(pyb_config_main)); + } + if (!do_file(vstr_str(vstr))) { + printf("Unable to open '%s'\n", vstr_str(vstr)); + flash_error(3); + } + vstr_free(vstr); + } + do_repl(); printf("PYB: soft reboot\n"); diff --git a/teensy/memzip.c b/teensy/memzip.c new file mode 100644 index 0000000000..ec6c26980c --- /dev/null +++ b/teensy/memzip.c @@ -0,0 +1,37 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include "memzip.h" + +extern uint8_t _staticfs[]; + +MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len) +{ + const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)_staticfs; + uint8_t *mem_data; + + /* Zip file filenames don't have a leading /, so we strip it off */ + + if (*filename == '/') { + filename++; + } + while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) { + const char *file_hdr_filename = (const char *)&file_hdr[1]; + mem_data = (uint8_t *)file_hdr_filename; + mem_data += file_hdr->filename_len; + mem_data += file_hdr->extra_len; + if (!strncmp(file_hdr_filename, filename, file_hdr->filename_len)) { + /* We found a match */ + if (file_hdr->compression_method != 0) { + return MZ_FILE_COMPRESSED; + } + + *data = mem_data; + *len = file_hdr->uncompressed_size; + return MZ_OK; + } + mem_data += file_hdr->uncompressed_size; + file_hdr = (const MEMZIP_FILE_HDR *)mem_data; + } + return MZ_NO_FILE; +} diff --git a/teensy/memzip.h b/teensy/memzip.h new file mode 100644 index 0000000000..ecbd98763c --- /dev/null +++ b/teensy/memzip.h @@ -0,0 +1,73 @@ +#pragma pack(push, 1) + +#define MEMZIP_FILE_HEADER_SIGNATURE 0x04034b50 +typedef struct +{ + uint32_t signature; + uint16_t version; + uint16_t flags; + uint16_t compression_method; + uint16_t last_mod_time; + uint16_t last_mod_date; + uint32_t crc32; + uint32_t compressed_size; + uint32_t uncompressed_size; + uint16_t filename_len; + uint16_t extra_len; + + /* char filename[filename_len] */ + /* uint8_t extra[extra_len] */ + +} MEMZIP_FILE_HDR; + +#define MEMZIP_CENTRAL_DIRECTORY_SIGNATURE 0x02014b50 +typedef struct +{ + uint32_t signature; + uint16_t version_made_by; + uint16_t version_read_with; + uint16_t flags; + uint16_t compression_method; + uint16_t last_mod_time; + uint16_t last_mod_date; + uint32_t crc32; + uint32_t compressed_size; + uint32_t uncompressed_size; + uint16_t filename_len; + uint16_t extra_len; + uint16_t disk_num; + uint16_t internal_file_attributes; + uint32_t external_file_attributes; + uint32_t file_header_offset; + + /* char filename[filename_len] */ + /* uint8_t extra[extra_len] */ + +} MEMZIP_CENTRAL_DIRECTORY_HDR; + +#define MEMZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE 0x06054b50 +typedef struct +{ + uint32_t signature; + uint16_t disk_num; + uint16_t central_directory_disk; + uint16_t num_central_directories_this_disk; + uint16_t total_central_directories; + uint32_t central_directory_size; + uint32_t central_directory_offset; + uint16_t comment_len; + + /* char comment[comment_len] */ + +} MEMZIP_END_OF_CENTRAL_DIRECTORY; + +#pragma pack(pop) + +typedef enum { + MZ_OK = 0, /* (0) Succeeded */ + MZ_NO_FILE, /* (1) Could not find the file. */ + MZ_FILE_COMPRESSED, /* (2) File is compressed (expecting uncompressed) */ + +} MEMZIP_RESULT; + +MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len); diff --git a/teensy/memzip_files/boot.py b/teensy/memzip_files/boot.py new file mode 100644 index 0000000000..3fe9f05e53 --- /dev/null +++ b/teensy/memzip_files/boot.py @@ -0,0 +1 @@ +print("Executing boot.py") diff --git a/teensy/memzip_files/src/main.py b/teensy/memzip_files/src/main.py new file mode 100644 index 0000000000..8fc08db15e --- /dev/null +++ b/teensy/memzip_files/src/main.py @@ -0,0 +1,11 @@ +print("Executing main.py") + +x=pyb.led(1) +pyb.delay(100) +x=pyb.led(0) +pyb.delay(100) +x=pyb.led(1) +pyb.delay(100) +x=pyb.led(0) + + diff --git a/teensy/memzip_files/src/test.py b/teensy/memzip_files/src/test.py new file mode 100644 index 0000000000..7957b27caf --- /dev/null +++ b/teensy/memzip_files/src/test.py @@ -0,0 +1 @@ +print("Executing /src/test.py") diff --git a/teensy/memzip_files/test.py b/teensy/memzip_files/test.py new file mode 100644 index 0000000000..088cb4383a --- /dev/null +++ b/teensy/memzip_files/test.py @@ -0,0 +1 @@ +print("Executing /test.py") diff --git a/teensy/mk20dx256.ld b/teensy/mk20dx256.ld index da57cbe5cb..e46efd3e26 100644 --- a/teensy/mk20dx256.ld +++ b/teensy/mk20dx256.ld @@ -126,6 +126,12 @@ SECTIONS _edata = .; } > RAM + /* + * _staticfs is the place in flash where the static filesystem which + * is concatenated to the .hex file will wind up. + */ + _staticfs = LOADADDR(.data) + SIZEOF(.data); + .noinit (NOLOAD) : { *(.noinit*) } > RAM diff --git a/tests/basics/run-tests b/tests/basics/run-tests index 0c3995da15..bc2969ae3d 100755 --- a/tests/basics/run-tests +++ b/tests/basics/run-tests @@ -42,4 +42,7 @@ echo "$numpassed tests passed" if [[ $numfailed != 0 ]] then echo "$numfailed tests failed -$namefailed" + exit 1 +else + exit 0 fi diff --git a/tests/basics/tests/containment.py b/tests/basics/tests/containment.py new file mode 100644 index 0000000000..84d40b4e8f --- /dev/null +++ b/tests/basics/tests/containment.py @@ -0,0 +1,23 @@ +for i in 1, 2: + for o in {1:2}, {1}, {1:2}.keys(): + print("{} in {}: {}".format(i, o, i in o)) + print("{} not in {}: {}".format(i, o, i not in o)) + +haystack = "supercalifragilistc" +for needle in (haystack[i:] for i in range(len(haystack))): + print(needle, "in", haystack, "::", needle in haystack) + print(needle, "not in", haystack, "::", needle not in haystack) + print(haystack, "in", needle, "::", haystack in needle) + print(haystack, "not in", needle, "::", haystack not in needle) +for needle in (haystack[:i+1] for i in range(len(haystack))): + print(needle, "in", haystack, "::", needle in haystack) + print(needle, "not in", haystack, "::", needle not in haystack) + print(haystack, "in", needle, "::", haystack in needle) + print(haystack, "not in", needle, "::", haystack not in needle) + +# until here, the tests would work without the 'second attempt' iteration thing. + +for i in 1, 2: + for o in [], [1], [1, 2]: + print("{} in {}: {}".format(i, o, i in o)) + print("{} not in {}: {}".format(i, o, i not in o)) diff --git a/tests/basics/tests/enumerate.py b/tests/basics/tests/enumerate.py new file mode 100644 index 0000000000..f2bdf4f326 --- /dev/null +++ b/tests/basics/tests/enumerate.py @@ -0,0 +1,6 @@ +print(list(enumerate([]))) +print(list(enumerate([1, 2, 3]))) +print(list(enumerate([1, 2, 3], 5))) +print(list(enumerate([1, 2, 3], -5))) +print(list(enumerate(range(10000)))) + diff --git a/tests/basics/tests/eval1.py b/tests/basics/tests/eval1.py new file mode 100644 index 0000000000..8b9d02e61b --- /dev/null +++ b/tests/basics/tests/eval1.py @@ -0,0 +1,13 @@ +# builtin eval + +eval('1 + 2') +eval('1 + 2\n') +eval('1 + 2\n\n#comment\n') + +x = 4 +eval('x') + +eval('lambda x: x + 10')(-5) + +y = 6 +eval('lambda: y * 2')() diff --git a/tests/basics/tests/exception1.py b/tests/basics/tests/exception1.py new file mode 100644 index 0000000000..71d5ad3041 --- /dev/null +++ b/tests/basics/tests/exception1.py @@ -0,0 +1,9 @@ +print(repr(IndexError())) +print(str(IndexError())) + +print(repr(IndexError("foo"))) +print(str(IndexError("foo"))) + +a = IndexError(1, "test", [100, 200]) +print(repr(a)) +print(str(a)) diff --git a/tests/basics/tests/filter.py b/tests/basics/tests/filter.py new file mode 100644 index 0000000000..5883e3d00b --- /dev/null +++ b/tests/basics/tests/filter.py @@ -0,0 +1,2 @@ +print(list(filter(lambda x: x & 1, range(-3, 4)))) +print(list(filter(None, range(-3, 4)))) diff --git a/tests/basics/tests/int-small.py b/tests/basics/tests/int-small.py new file mode 100644 index 0000000000..be338c4a4c --- /dev/null +++ b/tests/basics/tests/int-small.py @@ -0,0 +1,26 @@ +# This test small int range for 32-bit machine + +a = 0x3fffff +print(a) +a *= 0x10 +print(a) +a *= 0x10 +print(a) +a += 0xff +print(a) +# This would overflow +#a += 1 + +a = -0x3fffff +print(a) +a *= 0x10 +print(a) +a *= 0x10 +print(a) +a -= 0xff +print(a) +# This still doesn't overflow +a -= 1 +print(a) +# This would overflow +#a -= 1 diff --git a/tests/basics/tests/is-isnot.py b/tests/basics/tests/is-isnot.py new file mode 100644 index 0000000000..990190aa41 --- /dev/null +++ b/tests/basics/tests/is-isnot.py @@ -0,0 +1,14 @@ +print(1 is 1) +print(1 is 2) +print(1 is not 1) +print(1 is not 2) + + +print([1, 2] is [1, 2]) +a = [1, 2] +b = a +print(b is a) + +# TODO: strings require special "is" handling, postponed +# until qstr refactor. +#print("a" is "a") diff --git a/tests/basics/tests/list_compare.py b/tests/basics/tests/list_compare.py new file mode 100644 index 0000000000..eea8814247 --- /dev/null +++ b/tests/basics/tests/list_compare.py @@ -0,0 +1,50 @@ +print([] == []) +print([] > []) +print([] < []) +print([] == [1]) +print([1] == []) +print([] > [1]) +print([1] > []) +print([] < [1]) +print([1] < []) +print([] >= [1]) +print([1] >= []) +print([] <= [1]) +print([1] <= []) + +print([1] == [1]) +print([1] != [1]) +print([1] == [2]) +print([1] == [1, 0]) + +print([1] > [1]) +print([1] > [2]) +print([2] > [1]) +print([1, 0] > [1]) +print([1, -1] > [1]) +print([1] > [1, 0]) +print([1] > [1, -1]) + +print([1] < [1]) +print([2] < [1]) +print([1] < [2]) +print([1] < [1, 0]) +print([1] < [1, -1]) +print([1, 0] < [1]) +print([1, -1] < [1]) + +print([1] >= [1]) +print([1] >= [2]) +print([2] >= [1]) +print([1, 0] >= [1]) +print([1, -1] >= [1]) +print([1] >= [1, 0]) +print([1] >= [1, -1]) + +print([1] <= [1]) +print([2] <= [1]) +print([1] <= [2]) +print([1] <= [1, 0]) +print([1] <= [1, -1]) +print([1, 0] <= [1]) +print([1, -1] <= [1]) diff --git a/tests/basics/tests/map.py b/tests/basics/tests/map.py new file mode 100644 index 0000000000..62dca44ede --- /dev/null +++ b/tests/basics/tests/map.py @@ -0,0 +1,4 @@ +print(list(map(lambda x: x & 1, range(-3, 4)))) +print(list(map(abs, range(-3, 4)))) +print(list(map(set, [[i] for i in range(-3, 4)]))) +print(list(map(pow, range(4), range(4)))) diff --git a/tests/basics/tests/set_add.py b/tests/basics/tests/set_add.py new file mode 100644 index 0000000000..f2a372f307 --- /dev/null +++ b/tests/basics/tests/set_add.py @@ -0,0 +1,5 @@ +s = {1, 2, 3, 4} +print(s.add(5)) +l = list(s) +l.sort() +print(l) diff --git a/tests/basics/tests/set_binop.py b/tests/basics/tests/set_binop.py new file mode 100644 index 0000000000..d0d0b8027b --- /dev/null +++ b/tests/basics/tests/set_binop.py @@ -0,0 +1,30 @@ +def r(s): + l = list(s) + l.sort() + return l +sets = [set(), {1}, {1, 2}, {1, 2, 3}, {2, 3}, {2, 3, 5}, {5}, {7}] +for s in sets: + for t in sets: + print(s, '|', t, '=', r(s | t)) + print(s, '^', t, '=', r(s ^ t)) + print(s, '&', t, '=', r(s & t)) + print(s, '-', t, '=', r(s - t)) + u = s.copy() + u |= t + print(s, "|=", t, '-->', r(u)) + u = s.copy() + u ^= t + print(s, "^=", t, '-->', r(u)) + u = s.copy() + u &= t + print(s, "&=", t, "-->", r(u)) + u = s.copy() + u -= t + print(s, "-=", t, "-->", r(u)) + + print(s, '==', t, '=', s == t) + print(s, '!=', t, '=', s != t) + print(s, '>', t, '=', s > t) + print(s, '>=', t, '=', s >= t) + print(s, '<', t, '=', s < t) + print(s, '<=', t, '=', s <= t) diff --git a/tests/basics/tests/set_clear.py b/tests/basics/tests/set_clear.py new file mode 100644 index 0000000000..6fda93f0fb --- /dev/null +++ b/tests/basics/tests/set_clear.py @@ -0,0 +1,3 @@ +s = {1, 2, 3, 4} +print(s.clear()) +print(list(s)) diff --git a/tests/basics/tests/set_copy.py b/tests/basics/tests/set_copy.py new file mode 100644 index 0000000000..2ea308b0db --- /dev/null +++ b/tests/basics/tests/set_copy.py @@ -0,0 +1,8 @@ +s = {1, 2, 3, 4} +t = s.copy() +s.add(5) +t.add(7) +for i in s, t: + l = list(i) + l.sort() + print(l) diff --git a/tests/basics/tests/set_difference.py b/tests/basics/tests/set_difference.py new file mode 100644 index 0000000000..26976116f3 --- /dev/null +++ b/tests/basics/tests/set_difference.py @@ -0,0 +1,21 @@ +def report(s): + l = list(s) + l.sort() + print(l) + +l = [1, 2, 3, 4] +s = set(l) +outs = [s.difference(), + s.difference({1}), + s.difference({1}, [1, 2]), + s.difference({1}, {1, 2}, {2, 3})] +for out in outs: + report(out) + +s = set(l) +print(s.difference_update()) +report(s) +print(s.difference_update({1})) +report(s) +print(s.difference_update({1}, [2])) +report(s) diff --git a/tests/basics/tests/set_discard.py b/tests/basics/tests/set_discard.py new file mode 100644 index 0000000000..baac26413c --- /dev/null +++ b/tests/basics/tests/set_discard.py @@ -0,0 +1,3 @@ +s = {1, 2} +print(s.discard(1)) +print(list(s)) diff --git a/tests/basics/tests/set_intersection.py b/tests/basics/tests/set_intersection.py new file mode 100644 index 0000000000..6f3dfc7414 --- /dev/null +++ b/tests/basics/tests/set_intersection.py @@ -0,0 +1,12 @@ +def report(s): + l = list(s) + l.sort() + print(l) + +s = {1, 2, 3, 4} +report(s) +report(s.intersection({1, 3})) +report(s.intersection([3, 4])) + +print(s.intersection_update([1])) +report(s) diff --git a/tests/basics/tests/set_isdisjoint.py b/tests/basics/tests/set_isdisjoint.py new file mode 100644 index 0000000000..7fb7e769bb --- /dev/null +++ b/tests/basics/tests/set_isdisjoint.py @@ -0,0 +1,6 @@ +s = {1, 2, 3, 4} +print(s.isdisjoint({1})) +print(s.isdisjoint([2])) +print(s.isdisjoint([])) +print(s.isdisjoint({7,8,9,10})) +print(s.isdisjoint([7,8,9,1])) diff --git a/tests/basics/tests/set_isfooset.py b/tests/basics/tests/set_isfooset.py new file mode 100644 index 0000000000..ce7952cd2c --- /dev/null +++ b/tests/basics/tests/set_isfooset.py @@ -0,0 +1,5 @@ +sets = [set(), {1}, {1, 2, 3}, {3, 4, 5}, {5, 6, 7}] +for i in sets: + for j in sets: + print(i.issubset(j)) + print(i.issuperset(j)) diff --git a/tests/basics/tests/set_iter.py b/tests/basics/tests/set_iter.py new file mode 100644 index 0000000000..2960177303 --- /dev/null +++ b/tests/basics/tests/set_iter.py @@ -0,0 +1,5 @@ +s = {1, 2, 3, 4} +l = list(s) +l.sort() +print(l) + diff --git a/tests/basics/tests/set_pop.py b/tests/basics/tests/set_pop.py new file mode 100644 index 0000000000..0cd478ce25 --- /dev/null +++ b/tests/basics/tests/set_pop.py @@ -0,0 +1,9 @@ +s = {1} +print(s.pop()) +try: + print(s.pop(), "!!!") +except KeyError: + pass +else: + print("Failed to raise KeyError") + diff --git a/tests/basics/tests/set_remove.py b/tests/basics/tests/set_remove.py new file mode 100644 index 0000000000..208ab137f3 --- /dev/null +++ b/tests/basics/tests/set_remove.py @@ -0,0 +1,9 @@ +s = {1} +print(s.remove(1)) +print(list(s)) +try: + print(s.remove(1), "!!!") +except KeyError: + pass +else: + print("failed to raise KeyError") diff --git a/tests/basics/tests/set_symmetric_difference.py b/tests/basics/tests/set_symmetric_difference.py new file mode 100644 index 0000000000..acf298385a --- /dev/null +++ b/tests/basics/tests/set_symmetric_difference.py @@ -0,0 +1,7 @@ +print({1,2}.symmetric_difference({2,3})) +print({1,2}.symmetric_difference([2,3])) +s = {1,2} +print(s.symmetric_difference_update({2,3})) +l = list(s) +l.sort() +print(l) diff --git a/tests/basics/tests/set_union.py b/tests/basics/tests/set_union.py new file mode 100644 index 0000000000..2adcc972c0 --- /dev/null +++ b/tests/basics/tests/set_union.py @@ -0,0 +1 @@ +print({1}.union({2})) diff --git a/tests/basics/tests/set_update.py b/tests/basics/tests/set_update.py new file mode 100644 index 0000000000..78cd763560 --- /dev/null +++ b/tests/basics/tests/set_update.py @@ -0,0 +1,12 @@ +def report(s): + l = list(s) + l.sort() + print(l) + +s = {1} +s.update() +report(s) +s.update([2]) +report(s) +s.update([1,3], [2,2,4]) +report(s) diff --git a/tests/basics/tests/sorted.py b/tests/basics/tests/sorted.py new file mode 100644 index 0000000000..bbec319460 --- /dev/null +++ b/tests/basics/tests/sorted.py @@ -0,0 +1,2 @@ +print(sorted(set(range(100)))) +print(sorted(set(range(100)), key=lambda x: x + 100*(x % 2))) diff --git a/tests/basics/tests/string_find.py b/tests/basics/tests/string_find.py new file mode 100644 index 0000000000..90063228f8 --- /dev/null +++ b/tests/basics/tests/string_find.py @@ -0,0 +1,11 @@ +print("hello world".find("ll")) +print("hello world".find("ll", None)) +print("hello world".find("ll", 1)) +print("hello world".find("ll", 1, None)) +print("hello world".find("ll", None, None)) +print("hello world".find("ll", 1, -1)) +print("hello world".find("ll", 1, 1)) +print("hello world".find("ll", 1, 2)) +print("hello world".find("ll", 1, 3)) +print("hello world".find("ll", 1, 4)) +print("hello world".find("ll", 1, 5)) diff --git a/tests/basics/tests/zip.py b/tests/basics/tests/zip.py new file mode 100644 index 0000000000..c0109094f4 --- /dev/null +++ b/tests/basics/tests/zip.py @@ -0,0 +1,2 @@ +print(list(zip())) +print(list(zip([1], {2,3}))) diff --git a/unix-cpy/Makefile b/unix-cpy/Makefile index d5397dac9a..4955ea0c50 100644 --- a/unix-cpy/Makefile +++ b/unix-cpy/Makefile @@ -11,9 +11,16 @@ ECHO = @echo # compiler settings CC = gcc -CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -Os -DUNIX #-DNDEBUG +CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -DUNIX LDFLAGS = -lm +#Debugging/Optimization +ifdef DEBUG +CFLAGS += -Og -ggdb +else +CFLAGS += -Os #-DNDEBUG +endif + # source files SRC_C = \ main.c \ diff --git a/unix-cpy/main.c b/unix-cpy/main.c index ea85e32757..7d56ceaf34 100644 --- a/unix-cpy/main.c +++ b/unix-cpy/main.c @@ -27,16 +27,29 @@ void do_file(const char *file) { mp_lexer_free(lex); } else { - // compile + // parse + qstr parse_exc_id; + const char *parse_exc_msg; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); + + if (pn == MP_PARSE_NODE_NULL) { + // parse error + mp_lexer_show_error_pythonic_prefix(lex); + printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_lexer_free(lex); + return; + } - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_lexer_free(lex); if (pn != MP_PARSE_NODE_NULL) { //printf("----------------\n"); //parse_node_show(pn, 0); //printf("----------------\n"); + + // compile mp_obj_t module_fun = mp_compile(pn, false); + //printf("----------------\n"); if (module_fun == mp_const_none) { diff --git a/unix/Makefile b/unix/Makefile index 9af86b9855..9055909fb4 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -11,9 +11,16 @@ ECHO = @echo # compiler settings CC = gcc -CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -Os -DUNIX #-DNDEBUG +CFLAGS = -I. -I$(PY_SRC) -Wall -Werror -ansi -std=gnu99 -DUNIX LDFLAGS = -lm +#Debugging/Optimization +ifdef DEBUG +CFLAGS += -Og -ggdb +else +CFLAGS += -Os #-DNDEBUG +endif + # source files SRC_C = \ main.c \ @@ -27,7 +34,9 @@ LIB = -lreadline $(PROG): $(BUILD) $(OBJ) $(ECHO) "LINK $<" $(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) +ifndef DEBUG $(Q)strip $(PROG) +endif $(Q)size $(PROG) $(BUILD)/%.o: %.c diff --git a/unix/file.c b/unix/file.c index 398aac0759..e15e82775c 100644 --- a/unix/file.c +++ b/unix/file.c @@ -15,7 +15,7 @@ typedef struct _mp_obj_fdfile_t { int fd; } mp_obj_fdfile_t; -static void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_fdfile_t *self = self_in; print(env, "<io.FileIO %d>", self->fd); } @@ -90,6 +90,8 @@ static mp_obj_t fdfile_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *ar static const mp_method_t rawfile_type_methods[] = { { "read", &mp_stream_read_obj }, + { "readall", &mp_stream_readall_obj }, + { "readline", &mp_stream_unbuffered_readline_obj}, { "write", &mp_stream_write_obj }, { "close", &fdfile_close_obj }, { NULL, NULL }, diff --git a/unix/main.c b/unix/main.c index 15a4000ab5..d89f39da70 100644 --- a/unix/main.c +++ b/unix/main.c @@ -37,14 +37,20 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind return; } - mp_parse_node_t pn = mp_parse(lex, input_kind); - mp_lexer_free(lex); + qstr parse_exc_id; + const char *parse_exc_msg; + mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_exc_id, &parse_exc_msg); if (pn == MP_PARSE_NODE_NULL) { // parse error + mp_lexer_show_error_pythonic_prefix(lex); + printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_lexer_free(lex); return; } + mp_lexer_free(lex); + //printf("----------------\n"); //parse_node_show(pn, 0); //printf("----------------\n"); @@ -63,7 +69,7 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind nlr_pop(); } else { // uncaught exception - mp_obj_print((mp_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR); printf("\n"); } } @@ -159,7 +165,7 @@ typedef struct _test_obj_t { int value; } test_obj_t; -static void test_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { +static void test_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { test_obj_t *self = self_in; print(env, "<test %d>", self->value); } |